Может ли сокет TCP/IP отправить меньше байтов, чем запрошено через write()/send()?

Исходя из моих базовых знаний, я ожидаю, что сокет, представляющий соединение TCP/IP, будет гарантировать доставку запрошенных данных. Итак, бывает ли когда-нибудь случай, когда возвращаемое значение send() или write() будет меньше количества запрошенных байтов?

Это подробно обсуждалось много лет назад на news:comp.protocols.tcp-ip, где тусовались все разработчики, и пришли к единому мнению, что Posix требует отправки всех данных в режиме блокировки, если не происходит прерывания. read() с другой стороны (1) блокируется до тех пор, пока не станет доступен хотя бы один байт, а затем (2) возвращает столько байтов, сколько доступно, без дальнейшей блокировки: опять же, в режиме блокировки. В неблокирующем режиме как чтение, так и запись могут возвращать короткие значения.

user207421 16.04.2024 01:15

@ user207421 Что означает news:comp.protocols.tcp-ip? Группа в этом стеке переполняется?

arm.u 16.04.2024 02:32

@arm.u Это URL-адрес (на схеме news — группа Usenet).

Toby Speight 16.04.2024 08:52
Как создать страницу входа в систему с помощью HTML с использованием CSS
Как создать страницу входа в систему с помощью HTML с использованием CSS
Создание страницы входа в систему является важной частью создания веб-сайта или приложения, требующего аутентификации пользователя. Простую страницу...
0
3
76
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ни send, ни write не гарантируют, что все отправленные данные действительно записываются в сокет. Вместо этого они возвращают количество записанных данных — и только для этих фактически записанных данных применяются гарантии надежности TCP.

Вместо того, чтобы слепо полагаться на send или write для записи всего, вызывающая сторона ДОЛЖНА проверить возвращаемое значение функции, чтобы узнать, сколько данных записано, и отправить оставшиеся данные позже с помощью другого вызова.

Техническое объяснение этому состоит в том, что эти функции на самом деле не осуществляют прямую запись к одноранговому узлу. Вместо этого данные передаются в буфер записи в сокет, размер которого ограничен. Если буфер заполнен, то send и write будут блокироваться (если сокет не установлен в неблокируемый режим) до тех пор, пока ОС не вытащит данные из буфера записи для отправки их партнеру. В противном случае эти функции будут добавлять данные в буфер отправки, но только до максимального размера буфера. Поскольку отправленные данные могут превысить доступное пространство в буфере, функция может записать меньше, чем задано, и вызывающая сторона должна справиться с этой ситуацией, проверив код возврата.

Отлично, спасибо, что поделились своими знаниями. Если возможно, не могли бы вы знать структуру данных ядра Linux, которая управляет этим буфером для сокета?

arm.u 16.04.2024 00:41

@arm.u: Я не знаком со структурами ядра Linux. Но в любом случае этот ответ не относится только к Linux.

Steffen Ullrich 16.04.2024 06:55

Другие вопросы по теме