2010-01-09 2 views
3

Я новичок в программировании, и я смущен насчет асинхронного программирования сокетов.C# асинхронный сокет BeginSend EndReceive

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

Из-за асинхронного характера не будет второго BeginSend до первого?

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

ответ

7

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

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

Посмотрите пример Using an Asynchronous Client Socket на 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 < Message.Length, и если она затем отправляет следующий фрагмент сообщения.

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

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

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

+0

+1 для предложения сначала создать что-то простое. –

+1

спасибо, Марк, это всегда так, как я строю свой сетевой код. Я делал это много времени, но всегда начинаю с простой простой начальной точки и работаю оттуда. – Fuzz

+0

Может ли кто-то объяснить, что они подразумевают под: Он предполагает глобальный ManualResetEvent с именем connectDone. – Eidenai

1

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

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

+0

да им посылает оба сообщения на тот же адрес/порт. – iTEgg

+0

Я думаю, что отправка, вероятно, будет работать, но я подозреваю, что сообщения станут чередующимися и непревзойденными. –

+0

это проблема. как я могу избежать этого? это можно сделать, потому что приложения, такие как mirc, все время сталкиваются с такими проблемами. Я хотел бы знать, как я могу это реализовать? – iTEgg

Смежные вопросы