У Microsoft есть хороший пример асинхронного TCP-сервера. Требуется немного, чтобы обернуть голову вокруг этого. Прошло несколько часов моего собственного времени, прежде чем я смог создать базовую платформу TCP для своей собственной программы на основе этого примера.
http://msdn.microsoft.com/en-us/library/fx6588te.aspx
Логика программы выглядит примерно так. Есть один поток, который вызывает listener.BeginAccept, а затем блокирует allDone.WaitOne. BeginAccept - это асинхронный вызов, который выгружается в пул потоков и обрабатывается операционной системой. Когда приходит новое соединение, ОС вызывает метод обратного вызова, переданный из BeginAccept. Этот метод переворачивает allDone, чтобы основной прослушивающий поток знал, что он может прослушивать еще раз. Метод обратного вызова является просто переходным методом и продолжает вызывать еще один асинхронный вызов для получения данных.
Предоставленный метод обратного вызова, ReadCallback, является основным рабочим "циклом" (эффективно рекурсивными асинхронными вызовами) для асинхронных вызовов. Я свободно использую термин «цикл», потому что каждый вызов метода фактически завершается, но не до вызова следующего асинхронного метода. По сути, у вас есть куча асинхронных вызовов, вызывающих друг друга, и вы передаете свой объект «состояние». Этот объект является вашим собственным объектом, и вы можете делать с ним все, что захотите.
Каждый метод обратного вызова возвращает только две вещи, когда ОС вызывает ваш метод:
1) Сокет Объект, представляющий соединение
2) Состояние объекта, с которым вы используете свою логику
С вашим объектом состояния и объектом сокета вы можете эффективно обрабатывать ваши "соединения" асинхронно. ОС очень хороша в этом.
Кроме того, поскольку ваш основной цикл блокирует ожидание соединения и выгружает эти соединения в пул потоков с помощью асинхронных вызовов, он большую часть времени простаивает. Пул потоков для ваших сокетов обрабатывается ОС через порты завершения, поэтому они не выполняют никакой реальной работы, пока не поступят данные. Очень мало ЦП используется, и он эффективно пронизывается через пул потоков.
P.S. Из того, что я понимаю, вы не хотите выполнять какую-либо сложную работу с этими методами, просто обрабатывая перемещение данных. Поскольку пул потоков является пулом для вашего сетевого ввода-вывода и используется другими программами, вы должны разгрузить любую тяжелую работу с помощью потоков / заданий / асинхронных операций, чтобы пул потоков сокетов не зависал.
P.P.S. Я не нашел способа закрыть соединение для прослушивания, кроме как просто избавиться от «слушателя». Поскольку вызывается асинхронный вызов beginListen, этот метод никогда не вернется до тех пор, пока не будет установлено соединение, а это значит, что я не могу сказать ему прекратить, пока оно не вернется. Я думаю, что я отправлю вопрос на MSDN об этом. и ссылку, если я получу хороший ответ.