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

Предположим, что я действительно быстро записываю данные [у меня есть все данные в памяти] в блокирующий сокет. предположим, что другая сторона будет считывать данные очень медленно [например, спать 1 секунду между каждым чтением].

каково ожидаемое поведение на стороне письма в этом случае? будет блок операции записи, пока другая сторона не прочтет достаточное количество данных, или будет ли запись возвращать ошибку, такую ​​как соединение reset?

Ответы

Ответ 1

Для блокирующего сокета вызов send() блокируется до тех пор, пока все данные не будут скопированы в буфер сетевого стека для этого соединения. Он не должен приниматься другой стороной. Размер этого буфера зависит от реализации.

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

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

В обоих случаях небольшие системы (например, встроенные системы) могут иметь буферы с несколькими КБ или меньше, а современные серверы могут иметь буферы в несколько МБ или более.

Как только пространство будет доступно в локальном буфере, будет скопировано больше данных из вашего вызова send(). После того, как все эти данные будут скопированы, ваш вызов вернется.

Вы не получите сообщение об ошибке "connection reset" (из библиотеки OS могут делать что-либо), если соединение действительно не получает reset.

Итак... Неважно, насколько быстро удаленное приложение считывает данные, пока вы не отправите столько данных, сколько объединенных как локальный, так и удаленный размер буфера. После этого вы сможете использовать send() так же быстро, как удаленная сторона будет recv().

Ответ 2

Буфер вывода (отправки) заполняется до тех пор, пока он не будет заполнен, а блок send() блокируется до тех пор, пока буфер не станет достаточно свободным для размещения пакета.

В качестве отправной страницы руководства говорится:

Когда сообщение не помещается в буфер отправки сокета,      send() обычно блокирует, если сокет не был помещен в не-      блокирующий режим ввода/вывода.

Посмотрите на это: http://manpages.ubuntu.com/manpages/lucid/man2/send.2.html