Протокол UDP (User Datagram Protocol) обеспечивает передачу дейтаграмм в сетях IP. Реализация UDP в Linux соответствует спецификации RFC 768. Протокол обеспечивает передачу дейтаграмм без организации прямых соединений и без гарантии доставки пакетов. При передаче пакетов может нарушаться порядок доставки, некоторые пакеты могут теряться, а некоторые дублироваться. Для обнаружения ошибок при передаче пакетов протокол UDP использует контрольные суммы в заголовках пакетов.
При создании сокета UDP адреса (локальный и удаленный) не указываются. Дейтаграммы можно передавать сразу же после создания сокета с помощью функций sendto и sendmsg, которым в качестве параметра передается корректный адрес получателя. При вызове для сокета функции connect устанавливается принятый по умолчанию адрес получателя и дейтаграммы можно передавать с помощью функций send и write без указания адреса получателя. Если дейтаграммы нужно передавать по другим адресам, можно использовать функции sendto и sendmsg. Для приема входящих пакетов сокет должен быть связан с локальным адресом с помощью функции bind. Если функция вызвана без локального адреса, сокет связывается с первым свободным портом из числа указанных в net.ipv4.ip_local_port_range и адресом INADDR_ANY.
Все операции приема возвращают только один пакет. Когда размер пакета меньше размера буфера, возвращается только часть буфера, содержащая пакет. Если пакет превышает размер буфера, часть пакета отсекается с установкой для этого пакета флага MSG_TRUNC. Режим MSG_WAITALL реализацией протокола не поддерживается.
Опции IP могут передаваться или приниматься с использованием стандартных способов, описанных для протокола IP. Для обработки опций ядром требуется наличие соответствующих флагов SysCtl, но пользовательским программам опции будут передаваться в любом случае.
При установленном флаге MSG_DONTROUTE для передаваемых дейтаграмм адрес получателя должен быть связан с локальным интерфейсом и пакет может передаваться только через этот интерфейс.
UDP фрагментирует пакеты, когда общий размер превышает значение MTU для интерфейса. Более эффективным способом является определение MTU для маршрута доставки с помощью опции IP_PMTU_DISCOVER.
Формат адреса
Протокол UDP использует формат адресов Ipv4, передаваемых в структурах sockaddr_in.
Обработка ошибок
Сообщения о всех критических ошибках будут передаваться пользователю с возвратом кода ошибки даже в тех случаях, когда сокет не подключен. К числу критических ошибок относятся и асинхронные ошибки в сети. Приложение может также получать сообщения об ошибках для пакетов, которые были ранее отправлены в сеть с использованием данного сокета. Такое поведение отличается от большинства реализаций BSD, которые никогда не передают ошибок для неподключенных сокетов. Реализация Linux соответствует требованиям RFC 1122.
Для обеспечения совместимости со старыми версиями можно установить опцию сокета SO_BSDCOMPAT, обеспечивающую получение сообщений об ошибках только при подключенном сокете. Однако более эффективным решением будет замена старого кода, не обеспечивающего корректную обработку ошибок. Сообщения о локальных ошибках передаются в любом случае.
При включенной опции IP_RECVERR все сообщения об ошибках сохраняются в очереди сокета и могут быть прочитаны с помощью функции recvmsg, которой передается флаг MSG_ERRQUEUE.
Операции IOCTL
Функция ioctl позволяет определить размер ожидающей дейтаграммы и количество данных в очереди передачи в байтах.
Таблица 1 Операции IOCTL для протокола UDP
Тип
|
Описание
|
SIOCINQ
|
Возвращает указатель на целое число, определяющее размер ожидающей обработки дейтаграммы в байтах.
|
SIOCOUTQ
|
Возвращает указатель на целое число, показывающее объем данных (в байтах) в локальной очереди передачи. Поддерживается, начиная с ядра версии 2.4.
|
Кроме того, поддерживаются все операции IOCTL, определенные для IP и socket.
Коды ошибок
Модуль UDP может возвращать все коды ошибок, определенные для IP и socket.
Таблица 2 Сообщения об ошибках для протокола UDP
Ошибка
|
Описание
|
ECONNREFUSED
|
С указанным адресом не связано никакого получателя. Причина такого сообщения может быть связана с пакетом, переданным через данный сокет ранее.
|
|