9.9. UDP – отправь пакет и надейся на лучшее

UDP, протокол пользовательских датаграмм (User Datagram Protocol), – более простой из двух сервисов, которые предлагает транспортный уровень. Каждая отправка по UDP – это одна датаграмма: самодостаточный фрагмент байтов, адресованный некоторому IP и порту, выпущенный в сеть сам по себе. Протокол доставляет её, если может; если не может, он не повторяет попытку, не предупреждает отправителя и не сохраняет какого-либо порядка между датаграммами.

9.9.1. Что UDP добавляет к IP

UDP – это тонкий слой поверх IP. К сырой доставке IP он добавляет три вещи:

  • Номера портов на обоих концах, чтобы датаграмма могла быть доставлена нужной программе на узле назначения, а не просто узлу (см. Порты).

  • Поле длины, чтобы получатель точно знал, сколько байтов полезной нагрузки нужно прочитать.

  • Небольшую контрольную сумму по заголовку и полезной нагрузке, чтобы получатель мог обнаружить повреждённую датаграмму и отбросить её.

Вот и всё. Всё остальное, что IP делал или не делал, UDP сохраняет. Датаграммы не повторяются. Они могут приходить не по порядку. Они могут дублироваться из-за особенностей нижележащей сети. Они могут быть молча отброшены, если сеть перегружена, буфер в месте назначения заполнен или один из маршрутизаторов на пути так решит.

Диаграмма с отправителем слева и получателем справа. Три стрелки указывают от отправителя к получателю, с подписями "datagram 1", "datagram 2", "datagram 3". Стрелка для datagram 2 показана пунктирной линией с перечёркнутым крестом, обозначающим потерю.

Каждая датаграмма UDP отправляется независимо. Если одна теряется в пути, об этом ничего не сообщается ни отправителю, ни получателю – разрыв происходит молча.

9.9.2. Зачем вообще кому-то его использовать

Если UDP так ненадёжен, зачем он вообще нужен? Три причины.

  • Скорость и накладные расходы. Отправка по UDP – это один уходящий пакет; ни рукопожатия, ни подтверждений, ни состояния соединения, которое нужно поддерживать. Задержка и затраты на полосу пропускания минимальны.

  • Независимые сообщения. Часть трафика – это поток обновлений статуса, где каждое сообщение является свежим снимком, а старое не имеет ценности. Камера, публикующая «я всё ещё жива, вот моё текущее показание» каждую секунду, заботится о доставке каждого нового показания, а не о повторной передаче показаний, которые были потеряны.

  • Многоадресная рассылка (multicast). Одну датаграмму UDP можно отправить сразу многим получателям. (TCP так не может; каждое TCP-соединение существует ровно между двумя конечными точками.) Полезно для обнаружения сервисов, телеметрии многим слушателям, потоковой передачи видео.

Там, где сеть хороша, а терпимость отправителя к потерям высока, UDP – правильный ответ. Там, где доставка и порядок должны быть гарантированы, UDP либо нуждается в ещё одном слое надёжности поверх себя, либо приложению следует просто использовать вместо него TCP.

9.9.3. Когда не стоит его использовать

Об обратном тоже стоит сказать прямо. UDP – неправильный выбор, когда:

  • Важен каждый байт. Конфигурационные данные, обновления кода, подписанные транзакции – любой случай, где пропущенный байт делает результат неверным.

  • Важен порядок. Датаграмма UDP 2 может прийти раньше датаграммы 1.

  • Сообщение большое. Большие полезные нагрузки приложение должно разбивать на меньшие датаграммы; транспортный уровень этого не сделает. Если потеряется хотя бы один фрагмент, всё сообщение будет неполным.

Если применимо что-либо из этого, прибегайте к TCP.

9.9.4. Конкретные примеры на камере

Примеры UDP-трафика на стороне камеры в реальной жизни:

  • Обнаружение. При запуске камера широковещательно отправляет датаграмму «кто здесь» в локальную сеть; другие устройства отвечают.

  • Телеметрия. Раз в секунду камера отправляет коллектору небольшую датаграмму со своими текущими показаниями датчиков. Потеря случайной выборки не имеет значения, потому что следующая всё равно придёт через секунду.

  • Синхронизация времени. NTP, сетевой протокол времени, работает поверх UDP. Клиент отправляет небольшой запрос, сервер отвечает текущим временем; если ответ потерян, клиент просто спрашивает снова позже.

  • Поиск через DNS. Запрос к сети «какому IP соответствует это имя?» выполняется поверх UDP. (Рассмотрено в Имена и DNS.)

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