Какие условия вызывают блокировку NetworkStream.Write?

Будет ли NetworkStream.Write блокироваться только до тех пор, пока он не поместит данные для отправки в буфер отправки TCP, или он будет блокироваться до тех пор, пока принимающий хост не получит фактический ACK на данные?

Примечание. Сокет настроен на блокировку ввода-вывода.

Редактировать: Упс, TcpClient.Write, конечно же, не существует! Мы все поняли, что говорим о TcpClient.GetStream().Write, что на самом деле NetworkStream.Write!


person David Pfeffer    schedule 05.10.2011    source источник


Ответы (3)


Если .net не использует что-то другое, кроме winsock, то согласно ссылке на winsock:

Успешное завершение функции отправки не означает, что данные были успешно доставлены и получены получателем. Эта функция указывает только на то, что данные были успешно отправлены.

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

Если предположить, что запись вызывает отправку внизу, то строгая интерпретация документации winsock укажет, что нет никакой гарантии, что данные попадут на другой конец канала, когда они вернутся.

Вот ссылка на документы winsock, из которых я цитирую: http://msdn.microsoft.com/en-us/library/windows/desktop/ms741416(v=VS.85).aspx

person user957902    schedule 05.10.2011
comment
+1 за показ ссылки. Мне еще предстоит найти какую-либо другую документацию по этой теме, поэтому я предполагаю, что то, что вы цитируете, вероятно, верно. - person David Pfeffer; 06.10.2011
comment
+1 Хорошая работа над ссылкой (было удивительно трудно найти документацию по чему-то, что я считал само собой разумеющимся) - person tcarvin; 06.10.2011
comment
(И да, .NET использует сокеты ОС, которые Winsock в Windows.) - person David Pfeffer; 06.10.2011
comment
@user957902 user957902, так это означает, что в Windows мы никогда не знаем, были ли данные успешно получены на удаленном узле? Я сделал некоторые тесты, даже если я отключу кабель, данные все равно могут быть Write(bytes) без каких-либо исключений (я ждал там еще 20 минут). - person Shawn; 09.02.2015
comment
@Шон Это правильно. Вот почему существуют протоколы связи, которые возвращают подтверждение отправленных данных, чтобы вы знали, какие данные были получены на уровне приложения. По крайней мере, с потоком сокетов TCP вы знаете, что нижележащий стек протоколов требует, чтобы данные поступали в том порядке, в котором они были отправлены. - person user957902; 11.02.2015
comment
@user957902 user957902, поэтому я не понимаю, зачем выбирать TCP по сравнению с UDP, нам всегда нужно добавить какой-то механизм ACK на уровне приложения для обоих. - person Shawn; 12.02.2015
comment
@Shawn UDP не гарантирует, что данные, которые вы отправляете, поступят в том порядке, в котором они были отправлены, или если данные вообще попадают на другой конец. Это своего рода протокол отправки и молитвы. Таким образом, вы должны заботиться не только о том, чтобы данные попали на другой конец, но и о том, чтобы правильно их упорядочить после их поступления и определить, отсутствуют ли какие-либо фрагменты. Протокол TCP позаботится обо всем этом за вас. - person user957902; 12.02.2015

Я не согласен с обоими ответами [в которых говорится, что это блокирует]. Запись в сокет TCP/IP не блокируется, если базовый буфер уже не заполнен данными неподтверждения. Как правило, он не блокируется, а просто передается реализации TCP. Но, конечно, теперь мне нужно найти некоторые ссылки, чтобы подтвердить это :)

Из ТАК

person tcarvin    schedule 05.10.2011
comment
Кажется, я вижу, что ваш ответ правильный для Mono, тогда как другие ответы кажутся правильными для Windows. Я очень смущен. Надеюсь, вы найдете ссылки, потому что я не могу найти ничего убедительного. - person David Pfeffer; 06.10.2011

TcpClient.Write будет блокироваться до тех пор, пока буфер пакетов не будет сброшен в сеть и не будут получены соответствующие ACK. Вы заметите, что разорванное соединение обычно приводит к возникновению исключения в операции Write, поскольку оно ожидает ACK, но не получает его в течение определенного периода времени ожидания.

person Polynomial    schedule 05.10.2011