Если вы используете TCP, то вам потребуется один сокет для каждого клиента на стороне сервера, а также сокет для прослушивания соединений. Для UDP вы можете сделать все это с одним сокетом. Независимо от этого, сделайте следующее для вашего одного сокета UDP или для каждого сокета клиента TCP:
Пусть BeginReceive
происходит постоянно и BeginWrite
, когда происходит необходимое событие (т. Е. Пользователь нажимает кнопку или приходит сообщение, с которым вам нужно что-то предпринять).
РЕДАКТИРОВАТЬ: В ответ на ваш комментарий, я бы обработал его, включив в заголовок идентификатор запроса. Всякий раз, когда отправляете запрос (с любого конца), укажите уникальное значение для этого сообщения. Используйте Dictionary<RequestId, RequestState>
(с соответствующими заменами для типов) и посмотрите, относится ли входящее сообщение к уже существующему запросу. Кроме того, вы можете указать, что все идентификаторы с установленным старшим битом являются запросами, исходящими от клиента, а идентификаторы с очищенным старшим битом отправляются с сервера, чтобы избежать коллизий:
Server Client
Request 0x00 -------------> Starts processing
Starts processing <------- (unrelated) Request 0x80
Request 0x00 complete <---- Sends response to 0x00
Sends response to 0x80 ---> Request 0x80 complete
Эта система используется протоколом AOL OSCAR для (возможно, медленных) запросов с отслеживанием состояния.
EDIT2: Хм, хорошо ... вы действительно хотите заблокировать это? Что-то, что вы могли бы сделать, это иметь отдельный поток, обрабатывающий вызовы Send
/ Receive
. Этот поток будет связываться с основным потоком через потокобезопасную очередь «отправить сообщение» и аналогичную «полученную сообщение» очередь псевдо-сообщений. Причина, по которой я называю последнюю очередь псевдо-очередью, заключается в том, что вы хотели бы иметь возможность принимать сообщения из очереди не по порядку. Основной поток помещает сообщение в очередь отправки, а затем блокирует очередь приема. Каждый раз, когда поток сокетов обновляет очередь приема, основной поток просыпается и проверяет, есть ли еще нужное сообщение. Если это так, он возьмет его (из строя) и завершит требуемую операцию. Если сообщение еще не пришло, оно снова заблокируется в очереди. Когда операция, наконец, будет завершена, она просто возобновит нормальную работу и получит сообщения по порядку из очереди приема, обработает их или сделает все остальное.
Имеет ли это какой-то смысл? Извините, если это немного сбивает с толку ...