Async Socket Writes - Потенциал для операций отправки, чтобы быть перепутанным? (.NET Sockets) - PullRequest
4 голосов
/ 26 октября 2011

Извините, если раньше об этом спрашивали, но мне трудно искать:

Если я использую BeginSend() на сокете .NET , какое поведение я должен ожидать в коде, подобном этому (псевдо) коду:

Основной программный код:

Network.OutBound.SendData(messageOne);

Network.OutBound.SendData(messageTwo);

Network.OutBound класс

public void SendData(byte[] buffer)
{
     connectedSocket.BeginSend(buffer,0,buffer.Length,SocketFlags.None,SendCompleteMethod);
}

private void SendComplete(arResult)
{
     int bytesSent;
     bytesSent = arResult.EndSend();

     if(bytesSent < arResult.state.buffer.Length)
     {
         //Not all data sent yet, recall BeginSend
         connectedSocket.BeginSend(buffer,bytesSent,buffer.Length - bytesSent,SocketFlags.None,SendCompleteMethod);
     }
     else
     {
         //All data sent successfully
     }
}

Поскольку я использую BeginSend(), когда вызывается первый SendData(messageOne), он сразу же возвращается и вызывается второй SendData(messageTwo). Однако рассмотрим случай, когда большой объем данных отправляется как для первого, так и для второго сообщения, и отправка завершается с частичным объемом данных, и поэтому BeginSend() вызывается для отправки оставшихся данных.

Не приведет ли это к смешиванию байтов двух сообщений в исходящем сокете? Они оба будут работать в отдельных потоках пула потоков и будут отправлять данные в один и тот же сокет. Я понимаю, что сокеты TCP гарантируют, что данные поступают по порядку, но как уровень среды выполнения / сокета узнает, является ли моя BeginSend() попытка завершить отправку messageOne или начало messageTwo? Насколько это возможно, не будут ли данные отправляться и приниматься на удаленном конце в том же порядке, в котором они были записаны в сокет (даже если именно здесь, кажется, существует вероятность смешения)

Если это так, то какой смысл начинать / заканчивать отправку, если мне нужно сериализовать доступ к нему?

Если у меня есть какой-то флаг, который поднимается, когда messageOne полностью отправлено (даже если потребовалось несколько BeginSend() попыток отправить все данные), чтобы основной код программы мог дождаться его завершения, прежде чем пытаться отправить другое сообщение?

Должен ли я написать какую-нибудь оболочку исходящей очереди? Или я что-то упустил?

1 Ответ

3 голосов
/ 26 октября 2011

Заглянув в Reflector, вы увидите, что BeginSend наконец завершает работу из .NET-оболочек в Win32 API и вызывает WSASend , который, по-видимому, не предоставляет какой-либо опции ASync, поэтомуНасколько я вижу, он будет генерировать только блокирующие вызовы, которые управляются внутри .NET Framework и будут асинхронными с использованием пула потоков.

В приложениях, которые я написал для работы в сети, я никогда не задумывался над этой ситуацией, потому что у меня есть метод отправителя, который блокирует, если вы попытаетесь вызвать его снова, до того, как предыдущая отправка была завершена, или у меня естькоторый всегда блокируется с помощью .Send Only, потому что они обычно являются ответом на полученное сообщение в выделенном потоке.

РЕДАКТИРОВАТЬ:

Выполнено небольшое дополнительное тестирование.

Если вы начнете 2 начальных сеанса с небольшого буфера каждый, то это, вероятно, не будет иметь большого значения, но если ваш буфер имеет большое значение, в моих тестах я использовал буфер 400 Кб, тогда вы определенно попадете в мир боли, вынадеюсь, просто исключение, но оно сломается.

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