2017-01-04 6 views
18

В Mono 3.12 я использую Socket.SendAsync(SocketAsyncEventArgs) с потоком TCP Socket для реализации протокола потоковой передачи на основе запросов. Я использую SocketAsyncEventArgs.BufferList для установки нескольких буферов данных.Может ли выполнить операцию SendAsync TCP Socket без передачи всех байтов в BufferList?

В документации к Socket и SocketAsyncEventArgs, я не могу найти ни одного упоминания о том, можно ли SocketAsyncEventArgs.Completed быть поднят без всех байт посылается, когда BufferList используется, в результате чего создается впечатление, что мы должны подтвердить против SocketAsyncEventArgs.BytesTransferred.

С другой стороны, Socket.BeginSend делает это гарантия

Когда приложение вызывает BeginSend, система будет использовать отдельный поток для выполнения указанного метода обратного вызова, и будет блока на EndSendдо Socket отправляет количество байтов , запрашиваемое или генерирующее исключение.

Какие гарантии спецификации сделать о количестве байтов, переданных при использовании SendAsync с SocketAsyncEventArgs.BufferList?

Предположим, что мероприятие заполнено SocketError.Success.

+1

Я думаю, что вопрос будет следующим: «Можно ли вызывать обработчик' SocketAsyncEventArgs.Completed' без ошибки сокета и 'e.BytesTransferred! = Length'?" Из того, что я могу собрать в .NET Framework, невозможно: http://stackoverflow.com/questions/28675811/when-i-call-wsasend-will-all-the-data-be-sent и http: // stackoverflow .com/questions/14347708/call-wsasend-in-complete-port – jorgebg

+0

Можете ли вы предоставить код для тестирования? –

+0

@DieterMeemken Что вам нужно для тестирования, чтобы ответить _Что гарантирует ли спецификация make_? Как я уже упоминал, я использую 'SendAsync' с' SocketAsyncEventArgs' с набором 'BufferList'. –

ответ

1

Какие гарантии указывает спецификация на количество переданных байтов при использовании SendAsync с помощью SocketAsyncEventArgs.BufferList?

Для начала, событие может быть поднято при ошибках, и в этом случае вы можете предположить, что не все байты были переданы. Для этого вам нужно протестировать SocketAsyncEventArgs.SocketError для SocketError.Success. Кроме того, если вы ссылаетесь на «спецификацию», я предполагаю, что вы имеете в виду документацию Microsoft Windows Sockets (поскольку вы ссылаетесь на это для SendAsync и других описаний).

Для того, чтобы узнать, что в документации указано или подразумевается для количества переданных байтов при вызове события Completed в случае успеха, мы должны сделать несколько шагов. Первый шаг - посмотреть, использует ли SendAsync перекрывающиеся ввода-вывода. На этот вопрос ответят в документации Overlapped Input/Output. Реализация этого механизма является обязательной для основных поставщиков транспорта и, следовательно, является единственным перекрывающимся механизмом ввода-вывода, который гарантированно будет доступен для Windows Sockets. Таким образом, SendAsync гарантированно использует сокет с атрибутом WSA_FLAG_OVERLAPPED.

Обратите внимание, что проверка SendAsync reference implementation показывает, что SendAsync действительно использует WSASend с перекрывающимися вводами-выводами, но это всего лишь наблюдение.

Второй шаг - определить, какие перекрывающиеся ввода-вывода сообщают нам о передаче завершенного события, связанного с количеством переданных байтов. Эта ситуация описана в нескольких местах, например, на этой странице Overlapped I/I and Event Objects: «индикация будет указана при потреблении буферов отправки». В разделе замечаний для функции [WSASend] приводится более подробная информация: «Будет отображаться индикация завершения, вызывая завершение процедуры или установки объекта события, когда буфер (ы) были использованы транспортом», ,

Это все еще оставляет место для точной интерпретации этой фразы.В основном это говорит о том, что данные были приняты и подтверждены базовым транспортным механизмом из области сокета. Это не обязательно означает, что он достиг уровня удаленного протокола конечной точки, это будет зависеть от протокола связи. Для TCP-потокового сокета я бы сделал вывод, что он указывает, что данные достигли удаленной конечной точки.

Вывод состоит в том, что документация гарантирует (для ситуации без ошибок), что завершенное событие SendAsync возникает только в момент, когда все байты были переданы.

+0

Да, допустим только для SocketError.Success. Я отредактирую свой вопрос. Я не уверен. Когда я ссылаюсь на документацию, я намерен ссылаться на стандартные библиотеки .Net, которые должны быть реализованы во всех .Net-режимах, а не только для Windows. Реализация Windows делает это одним способом, но является ли это единственным правильным способом? –

-1

Что вы пытаетесь здесь проверить? Вас беспокоит, почему вы не получаете все байты, когда отправляются все байты?

Когда вы отправляете 100 байт за один выстрел и пытаетесь читать 100 байт на другом конце, нет гарантии, что вы получите все байты за один снимок. Он может быть разбит на 100 пакетов по 1 байт. Вот как работает TCP. Вам всегда нужно накапливать байты, а затем формировать и разделять ваши пакеты. Это называется усилением сантехники TCP. WCF и все эти обертки делают это за вас.