Я видел несколько вопросов относительно send()
, которые обсуждают базовый протокол. Я полностью понимаю, что для TCP любое сообщение может быть разбито на части по мере его отправки, и нет гарантии, что получатель получит сообщение в одной атомной операции. В этом вопросе я говорю исключительно о поведении системного вызова send()
, поскольку он взаимодействует с сетевым уровнем локальной системы.
В соответствии со стандартом POSIX и документацией send()
, которую я прочитал, длина отправляемого сообщения определяется аргументом length. Обратите внимание, что: send()
отправляет одно сообщение длины длины. Далее:
Если в отправляющем сокете место недоступно, чтобы сохранить сообщение передаваться, а дескриптор файла сокета не имеет
O_NONBLOCK
set,send()
должен блокироваться до тех пор, пока не будет доступно пространство. Если пространство недоступно в отправляющем сокете, чтобы сохранить сообщение передан, а дескриптор файла сокета имеет наборO_NONBLOCK
,send()
завершится с ошибкой.
Я не вижу никакой возможности в этом определении для send() когда-либо возвращать любое значение, отличное от -1
(что означает, что никакие данные не помещаются в ядре для передачи) или length, что означает, что все сообщение очереди в ядре, которое должно быть передано. I.e., мне кажется, что send()
должен быть атомарным относительно локального очередности сообщения для доставки в ядре.
- Если в ядре для ядра есть достаточное количество места для всего сообщения, и никакой сигнал не возникает (обычный случай), он копирует и возвращает длину.
- Если во время
send()
появляется сигнал, тогда он должен возвращать-1
. Очевидно, что в этом случае мы не можем поставить в очередь часть сообщения, так как мы не знаем, сколько было отправлено. Поэтому в этой ситуации ничего не может быть отправлено. - Если в очереди на ящик в ядре недостаточно места для всего сообщения, а сокет блокируется, то согласно вышеприведенному утверждению
send()
должен блокироваться, пока не станет доступным пространство. Затем сообщение будет поставлено в очередь иsend()
возвращает длину. - Если в ядре для ящика нет достаточного количества места для всего сообщения, а сокет не блокируется, то
send()
должен выйти из строя (return-1
), аerrno
будет установлен наEAGAIN
> илиEWOULDBLOCK
. Опять же, поскольку мы возвращаем-1
, ясно, что в этой ситуации никакая часть сообщения не может быть поставлена в очередь.
Я что-то упустил? Возможно ли отправить send() значение >=0 && <length
? В какой ситуации? Как насчет систем, отличных от POSIX/UNIX? Соответствует ли реализация Windows send()
этому?