Ответ 1
[Обновление 2014]: Кажется, что этот пример был изменен, поскольку этот ответ был опубликован, как отмечено в этом потоке. Пример MSDN теперь обрабатывает несколько входящих соединений должным образом. Во всяком случае, общий подход, описанный здесь, является правильным и, возможно, может дать дополнительное разъяснение.
При выполнении связи сокетов у вас в основном есть единственный прослушиватель сокет для всех входящих подключений и несколько сокетов обработчик для каждого подключенного клиента.
Прослушивание входящих соединений
Когда вы начинаете слушать порт, вы создаете сокет с методом обратного вызова для входящих соединений (это ссылается на пример, который вы упомянули). То, что для этого номера порта используется <единственный > список прослушивателя:
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
Эта строка сообщает слушателю вызывать метод AcceptCallback
всякий раз, когда подключается новый клиент (новый обратный вызов соединения). Этот метод позволяет быстро выполнять свою работу, поскольку он блокирует другие входящие соединения.
Создание выделенных сокетов-обработчиков
Вот почему AcceptCallback
должен немедленно создать выделенный "обработчик" с помощью собственного метода обработки данных:
// inside AcceptCallback, we switch to the handler socket for communication
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state); // fired on a background thread
С этого момента метод ReadCallback
вызывается всякий раз, когда ваш новый клиент получает ваш запрос.
Кроме того, перед возвратом AcceptCallback
необходимо снова вызвать listener.BeginAccept
, чтобы продолжить прослушивание новых входящих соединений:
// this is the same server socket we opened previously, which will now
// continue waiting for other client connections: it doesn't care about
// the actual data transmission between individual clients
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
Эта часть не указана в примере MSDN, что означает, что она может принимать только одно соединение.
Получение данных
Как только вы получите пакет данных от вашего клиента, будет вызван метод ReadCallback
. Таким образом, внутри этого метода обратного вызова данных вам необходимо прочитать и обработать полученные данные, а затем снова вызвать тот же метод BeginReceive
(опять же, с помощью ReadCallback
в качестве метода обратного вызова данных).
[изменить]
Проблема с примером MSDN заключается в том, что он позволяет подключать только одного клиента (listener.BeginAccept
вызывается только один раз). Чтобы разрешить параллельные соединения mulitple, вам необходимо создать приемный сокет с помощью handler.BeginReceive
, а затем вызвать listener.BeginAccept
, чтобы начать прослушивание новых клиентов.