Какие гарантии дает UDP? - PullRequest
       117

Какие гарантии дает UDP?

0 голосов
/ 06 августа 2020

UDP-пакеты, очевидно, могут приходить несколько раз, не совсем и не по порядку.

Но если пакеты приходят, гарантировано ли, что любой вызов recvfrom и аналогичных функций вернет ровно один полный пакет отправитель отправил через sendto (или аналогичный)? Другими словами, можно ли получать неполные пакеты или несколько пакетов одновременно? Это зависит от ОС или стандарт требует определенного поведения?

Ответы [ 2 ]

2 голосов
/ 06 августа 2020

Как я упомянул в комментарии, спецификация UDP ( RF C 768 ) не определяет поведение «интерфейса» между прикладной программой и инфраструктурой ОС, которая обрабатывает сообщения UDP.

Однако спецификация POSIX делает это адрес. Ключевой раздел recvfrom spe c говорит следующее:

Функция recvfrom() должна возвращать длину сообщения, записанного в буфер, на который указывает аргумент буфера. Для сокетов на основе сообщений, таких как SOCK_RAW, SOCK_DGRAM и SOCK_SEQPACKET, все сообщение должно быть прочитано за одну операцию. Если сообщение слишком длинное, чтобы поместиться в предоставленный буфер, и MSG_PEEK не установлен в аргументе флагов, лишние байты должны быть отброшены.

Обратите внимание на использование слова «должен». Любой API-интерфейс приложения OS <->, который утверждает, что он соответствует стандарту POSIX spe c, будет связан с этим языком.

Проще говоря, любой POSIX-совместимый recvfrom вернет одно полное сообщение UDP в буфере при условии, что предоставленное буферное пространство достаточно велико. Если он недостаточно велик, «лишние» байты будут отброшены.

(Некоторые реализации recvfrom поддерживают нестандартный флаг MSG_TRUNC, который позволяет приложению узнать фактическую длину сообщения. Проверьте Для ОС c подробности на странице руководства.)

0 голосов
/ 06 августа 2020

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

From the recv man page (выделено мной)

Если сообщение слишком длинное, чтобы поместиться в предоставленный буфер, избыточные байты могут быть отброшены в зависимости от типа сокета, на котором получено сообщение from.

Если в сокете нет доступных сообщений, вызовы приема ждут прибытия сообщения, если только сокет не является неблокирующим (см. fcntl (2)) в в этом случае возвращается значение -1, а для внешней переменной errno устанавливается значение EAGAIN или EWOULDBLOCK. Приемные вызовы обычно возвращают любые доступные данные, вплоть до запрошенной суммы, вместо ожидания получения полной запрошенной суммы.

Еще один фактор, который необходимо принять во внимание во внимание принимается внутренний размер буфера приема . Это фиксированный размер, и попытка добавить больше данных в уже заполненный буфер может привести к потере данных. Значение может быть установлено с помощью флага SO_RCVBUF - на странице сокета :

SO_RCVBUF Устанавливает или получает максимальный буфер приема сокета в байтах. Ядро удваивает это значение (чтобы освободить место для накладных расходов), когда оно устанавливается с помощью setsockopt (2), и это удвоенное значение возвращается getsockopt (2). Значение по умолчанию задается файлом / proc / sys / net / core / rmem_default, а максимально допустимое значение устанавливается файлом / proc / sys / net / core / rmem_max. Минимальное (удвоенное) значение для этой опции - 256.

...