Хранение подключенных клиентов?

В настоящее время я изучаю и работаю над клиентом/сервером, и у меня возникают трудности с тем, как хранить соединения.

Вот пример кода:

while (_isRunning)
{
    if (!tcpListener.Pending())
    {
        Thread.Sleep(200);
        continue;
    }

    TcpClient client = tcpListener.AcceptTcpClient();
    // TODO: handle connection
}

Я знаю, что у меня будет обработчик, который будет получать/отправлять данные этому данному клиенту, однако просто наличие обработчика не позволит мне делать такие вещи, как знание того, сколько клиентов подключено, отправка широковещательного сообщения или сообщение о завершении работы для всех.

Будет ли хорошо хранить клиента в списке или мне следует хранить что-то еще?

Как правильно хранить подключенных клиентов в этом случае?


person Guapo    schedule 27.09.2012    source источник
comment
Здесь может пригодиться Dictionary или List. List<TcpClient> должно быть достаточно.   -  person Matthew    schedule 27.09.2012
comment
@ Мэтью, да, но я имел в виду, будет ли достаточно списка? Должен ли я хранить какую-либо другую информацию помимо TcpClient, чтобы составить список подключенных клиентов? Я просто ищу ссылку на то, что было бы хорошим полезным способом, как это сделать.   -  person Guapo    schedule 27.09.2012
comment
Это будет зависеть от того, какая информация вас интересует. Если все, что вам нужно, это количество подключений и возможность транслировать сообщение, то простого списка TcpClient будет достаточно.   -  person Matthew    schedule 27.09.2012


Ответы (2)


Для наиболее распространенных шаблонов использования достаточно иметь List подключенных клиентов. Главной интересной задачей будет решение: список что?

Для многих приложений чистая функциональность TCP неудобна в использовании, поэтому вам понадобится слой поверх него, который преобразует поток в нечто более похожее на очередь сообщений, из которой можно извлекать целые автономные «сообщения»; формат этих сообщений зависит от вашего приложения.

Я откопал свой старый проект, который представляет собой конфигурацию клиент-сервер, в которой несколько клиентов подключаются к серверу и предлагают функции удаленного управления. В этом проекте сервер хранит List<ConnectedClient>, где:

// This is the whole actual class
private class ConnectedClient
{
    public TcpMessageConnection Connection { get; private set; }

    public bool ConnectedEventRaised { get; set; }

    public ConnectedClient(TcpMessageConnection connection)
    {
        this.Connection = connection;
    }
}

И TcpMessageConnection выглядит так:

// Only class outline shown
public class TcpMessageConnection
{
    private readonly MessageStream messageStream; // another custom class

    private readonly TcpClient tcpClient;

    public EndPoint RemoteEndPoint { get; private set; } // who connected here?

    public MessageReader MessageReader { get; } // messageStream.Reader

    public MessageWriter MessageWriter { get; } // messageStream.Writer

    public bool IsCurrentlyDisconnecting { get; private set; }

    public void Close();
}

Вместе с MessageReader и MessageWriter (которые выполняют настоящую тяжелую работу) этого достаточно для реализации асинхронного сервера, который обслуживает несколько клиентов в одном потоке.

person Jon    schedule 27.09.2012
comment
это довольно интересно, этот проект с открытым исходным кодом? Я хотел бы проверить больше в нем. Мне нравится, как он связывает подключенных пользователей, легко получить некоторые полезные данные, такие как IP, и я предполагаю, что вы закрываете, чтобы отправить закрытие или закрыть этого клиента? - person Guapo; 30.09.2012
comment
@Guapo: не с открытым исходным кодом, извините. Close просто закрывает MessageStream (который, в свою очередь, закрывает Stream TcpClient) и сам TcpClient. IsCurrentlyDisconnecting до этого устанавливается на true и используется в качестве защиты, поэтому остальная часть приложения не должна беспокоиться о спаме при закрытии и возникновении какой-либо ошибки. - person Jon; 03.10.2012

С сервером вас обычно не столько интересует сокет, сколько то, для чего он нужен. Подход, который я бы выбрал, состоял бы в том, чтобы иметь класс, который управляет серверной частью диалога между клиентом и сервером. Этот класс будет основан на потоке, поэтому идея состоит в том, что каждый раз, когда принимается соединение, вы запускаете поток для обработки диалога, и в этом потоке находится сокет для серверной части соединения.

На этом этапе вы будете управлять различными потоками, а не отдельными сокетами. Это более высокий уровень абстракции и более полезный.

То, как вы управляете потоками, будет зависеть от того, что вы хотите сделать. Возможно, вы действительно не хотите об этом беспокоиться. Поскольку каждый поток делает свое дело, по завершении он просто закрывает свой конец TCP-соединения и завершает работу.

Однако до тех пор, пока он не завершится, класс потока обрабатывает серверную часть диалога.

Я предлагаю вам проверить этот stackoverflow, Лучший способ принять несколько клиентов tcp .

person Richard Chambers    schedule 27.09.2012