UDP
| Полное название | User Datagram Protocol |
|---|---|
| Автор | Джон Постел |
| Спецификация | RFC 768 (1980) |
| Уровень | транспортный |
| Размер заголовка | 8 байт |
| Гарантии | нет — ни доставки, ни порядка, ни защиты от дубликатов |
| Применение | DNS, DHCP, NTP, VoIP и видеосвязь, игры, WireGuard, QUIC и HTTP/3 |
UDP (англ. User Datagram Protocol — протокол пользовательских датаграмм) — транспортный протокол стека TCP/IP, который отправляет отдельные сообщения — датаграммы — без установления соединения и без каких-либо гарантий: датаграмма может потеряться, прийти дважды или не по порядку, и протокол ничего с этим не делает. Взамен UDP прост, быстр и не добавляет задержек: никаких рукопожатий, подтверждений и повторных отправок.
UDP выбирают, когда опоздавшие данные бесполезны (голос, видео, игры), когда запрос и ответ умещаются в один пакет (DNS) или когда приложение хочет реализовать собственную надёжность поверх него, как QUIC.
История
Протокол описал Джон Постел в RFC 768 в 1980 году — документ занимает всего три страницы.[1] UDP появился, когда исходный монолитный протокол Серфа и Кана разделили на IP и TCP: стало ясно, что не всем приложениям нужна надёжная доставка, а некоторым — например, передаче речи — она даже вредит.
Устройство
Заголовок UDP занимает 8 байт и содержит четыре поля:
| Поле | Размер | Назначение |
|---|---|---|
| Порт отправителя | 2 байта | куда отвечать (может быть нулевым) |
| Порт получателя | 2 байта | какой программе доставить |
| Длина | 2 байта | размер датаграммы с заголовком |
| Контрольная сумма | 2 байта | проверка целостности |
Для сравнения: заголовок TCP — от 20 байт, плюс установление соединения, подтверждения и состояние на обеих сторонах. Каждая датаграмма UDP самостоятельна: границы сообщений сохраняются, в отличие от потока TCP.
UDP и TCP
| UDP | TCP | |
|---|---|---|
| Соединение | нет | тройное рукопожатие |
| Доставка | не гарантирована | гарантирована, с повторами |
| Порядок | не гарантирован | гарантирован |
| Границы сообщений | сохраняются | поток байтов |
| Управление перегрузкой | нет (ответственность приложения) | встроено |
| Широковещание и мультикаст | да | нет |
| Задержка | минимальная | выше, особенно при потерях |
Где используется
- DNS — короткий запрос и ответ помещаются в одну датаграмму; при потере клиент просто повторит запрос.
- DHCP — получение IP-адреса при подключении к сети, когда адреса ещё нет и соединение установить невозможно.
- NTP — синхронизация времени.
- Голос и видео — RTP поверх UDP: потерянный фрагмент лучше пропустить, чем ждать повтора и получить заикание.[3]
- Онлайн-игры — актуальное положение игроков важнее устаревшего.
- VPN — WireGuard и OpenVPN работают поверх UDP: внутренние TCP-соединения сами обеспечивают надёжность, а двойные повторы TCP-внутри-TCP только вредят.[5]
- QUIC и HTTP/3 — современный веб-транспорт, реализующий надёжность, шифрование и управление перегрузкой поверх UDP.[4]
- Мультикаст — рассылка одного потока многим получателям (IPTV, биржевые котировки).
Пример
import socket
# сервер
srv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
srv.bind(("0.0.0.0", 9999))
data, addr = srv.recvfrom(2048) # ждём одну датаграмму
srv.sendto(b"pong", addr)
# клиент
cli = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
cli.settimeout(1.0) # ответа может и не быть
cli.sendto(b"ping", ("127.0.0.1", 9999))
print(cli.recvfrom(2048))
Нет ни listen, ни accept, ни connect: каждая датаграмма отправляется по адресу отдельно. Таймаут и повтор — забота приложения.
nc -u -l 9999 # слушать UDP-порт
echo hello | nc -u host 9999 # отправить датаграмму
ss -ulnp # слушающие UDP-сокеты
Подводные камни
- Размер датаграммы. Датаграмма больше MTU пути (обычно около 1500 байт для Ethernet) фрагментируется на уровне IP, а потеря любого фрагмента губит её целиком; многие сети фрагменты отбрасывают. Протоколы поверх UDP стараются укладываться примерно в 1200–1400 байт.
- Ответственность приложения. Нужно самому решать, что делать с потерями, дубликатами и порядком, и не перегружать сеть: руководство RFC 8085 требует от протоколов поверх UDP собственного управления перегрузкой.[2]
- NAT и файрволы. Без соединения промежуточные устройства держат состояние UDP-«потоков» недолго; приложения шлют периодические пакеты поддержки.
- Атаки с усилением. Отправитель в UDP не проверяется, поэтому злоумышленник может подделать адрес жертвы и отправить маленький запрос к серверу, отвечающему большим ответом (открытые DNS-резолверы, NTP, memcached). Ответы обрушиваются на жертву — так устроены многие крупные DDoS-атаки.[6]