Подтвердить что ты не робот

Может ли операция TCP Socket SendAsync завершить без передачи всех байтов в BufferList?

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

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

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

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

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

Предположим, что событие было завершено SocketError.Success.

4b9b3361

Ответ 1

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

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

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

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

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

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

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

Ответ 2

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

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