Исходя из моих базовых знаний, я ожидаю, что сокет, представляющий соединение TCP/IP, будет гарантировать доставку запрошенных данных. Итак, бывает ли когда-нибудь случай, когда возвращаемое значение send()
или write()
будет меньше количества запрошенных байтов?
@ user207421 Что означает news:comp.protocols.tcp-ip
? Группа в этом стеке переполняется?
@arm.u Это URL-адрес (на схеме news
— группа Usenet).
Ни send
, ни write
не гарантируют, что все отправленные данные действительно записываются в сокет. Вместо этого они возвращают количество записанных данных — и только для этих фактически записанных данных применяются гарантии надежности TCP.
Вместо того, чтобы слепо полагаться на send
или write
для записи всего, вызывающая сторона ДОЛЖНА проверить возвращаемое значение функции, чтобы узнать, сколько данных записано, и отправить оставшиеся данные позже с помощью другого вызова.
Техническое объяснение этому состоит в том, что эти функции на самом деле не осуществляют прямую запись к одноранговому узлу. Вместо этого данные передаются в буфер записи в сокет, размер которого ограничен. Если буфер заполнен, то send
и write
будут блокироваться (если сокет не установлен в неблокируемый режим) до тех пор, пока ОС не вытащит данные из буфера записи для отправки их партнеру. В противном случае эти функции будут добавлять данные в буфер отправки, но только до максимального размера буфера. Поскольку отправленные данные могут превысить доступное пространство в буфере, функция может записать меньше, чем задано, и вызывающая сторона должна справиться с этой ситуацией, проверив код возврата.
Отлично, спасибо, что поделились своими знаниями. Если возможно, не могли бы вы знать структуру данных ядра Linux, которая управляет этим буфером для сокета?
@arm.u: Я не знаком со структурами ядра Linux. Но в любом случае этот ответ не относится только к Linux.
Это подробно обсуждалось много лет назад на
news:comp.protocols.tcp-ip
, где тусовались все разработчики, и пришли к единому мнению, что Posix требует отправки всех данных в режиме блокировки, если не происходит прерывания.read()
с другой стороны (1) блокируется до тех пор, пока не станет доступен хотя бы один байт, а затем (2) возвращает столько байтов, сколько доступно, без дальнейшей блокировки: опять же, в режиме блокировки. В неблокирующем режиме как чтение, так и запись могут возвращать короткие значения.