C # асинхронный сокет BeginSend EndReceive - PullRequest
3 голосов
/ 09 января 2010

Я новичок в программировании и запутался в асинхронном программировании сокетов.

Например, скажем, у меня есть два BeginSend, один за другим. Первый отправляет миллион символов, а второй - только 64 символа.

Из-за асинхронной природы второй BeginSend не завершится раньше первого?

Если так, как я могу узнать полученные данные на EndRecieve, к какому сообщению относится?

Ответы [ 2 ]

7 голосов
/ 09 января 2010

Вы действительно не должны вызывать два BeginSend один за другим. Я думаю, что вы в конечном итоге увидите исключения, если это произойдет.

Вы должны вызвать EndSend перед вызовом другого BeginSend. Обычно это делается в стороне от функции обратного вызова.

Ознакомьтесь с примером Использование асинхронного клиентского сокета в MSDN. В обратном вызове вызывается EndSend, а затем устанавливается ManualResetEvent с именем «sendDone». Это форма связи между потоками, при которой обратный вызов сигнализирует вашему основному потоку, что асинхронная отправка завершена. Это позволяет вашей программе отслеживать следующий фрагмент данных.

  • Вызовите BeginSend из основного потока, чтобы отправить первые 1 000 000 байтов
  • Ваш основной поток может проверять семафор или что-то вроде ManualResetEvent, чтобы запускать его для отправки следующих 64 байтов. Другой вариант - использовать очередь для отправки данных
  • Когда данные закончат отправку, будет вызван обратный вызов, переданный вами в BeginSend.
  • В этом обратном вызове вы будете вызывать EndSend. Затем выполните настройку ManualResetEvent или любого триггерного потока, который вы хотите использовать.

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

например.

int NumBytesSent; // member variable containing how many bytes you have sent so far
string Message;   // Message to send that is large

Когда вы вызываете BeginSend, передайте порцию, скажем, 100 байт (выберите большее число для более эффективной передачи, но не слишком большой), чтобы отправить и увеличить NumBytesSend на 100. Затем, в вашем обратном вызове для предыдущей завершенной отправки вы можете проверить, если NumBytesSent

Так вы бы отправляли файл, отправляя сразу несколько байтов, и просто продолжали посылать фрагменты файла до тех пор, пока он не будет отправлен.

Я настоятельно рекомендую сделать простой клиент / сервер, чтобы сделать что-то вроде отправки полного файла через соединение. Также ознакомьтесь с документами MSDN и множеством других примеров в Интернете.

Хорошее понимание этого поможет вам во многих других темах C #, поскольку асинхронная работа (или использование делегатов / обратных вызовов) очень распространена для .NET

1 голос
/ 09 января 2010

Метод BeginSend включает параметр AsyncCallback callback. Если вы используете два разных обратных вызова, вы можете увидеть, какой из них завершился первым.

Но если вы пытаетесь отправить оба сообщения по одному и тому же соединению, у вас будут проблемы. Вам следует подождать, пока первое сообщение полностью не будет отправлено, прежде чем отправлять второе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...