Я видел несколько вопросов относительно send(), которые обсуждают базовый протокол. Я полностью понимаю, что для TCP любое сообщение может быть разбито на части по мере его отправки, и нет гарантии, что получатель получит сообщение в одной атомной операции. В этом вопросе я говорю исключительно о поведении системного вызова send(), поскольку он взаимодействует с сетевым уровнем локальной системы.
В соответствии со стандартом POSIX и документацией send(), которую я прочитал, длина отправляемого сообщения определяется аргументом length. Обратите внимание, что: send() отправляет одно сообщение длины длины. Далее:
Если в отправляющем сокете место недоступно, чтобы сохранить сообщение передаваться, а дескриптор файла сокета не имеет
O_NONBLOCKset,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() этому?