Автор проекта под ником by_cortex опубликовал на Habr подробный разбор реализации собственного надежного протокола доставки данных (RDT) поверх ненадежного UDP. Проект, получивший название Protocol-7 (P7), написан на чистом Си и демонстрирует, как можно воссоздать ключевые механизмы TCP, не полагаясь на ядро ОС. Главная цель заключалась не в замене системного стека, а в глубоком понимании сетевых механизмов и создании работающего аналога с поддержкой скользящего окна, SACK и таймаутов.
Архитектура и заголовок P7
В отличие от стандартного TCP, где заголовок занимает минимум 20 байт, авторы P7 оптимизировали структуру, сделав её фиксированной и компактной. Заголовок занимает ровно 12 байт, что позволяет экономить полезную нагрузку. Порты и IP-адреса не дублируются в заголовке P7, а извлекаются напрямую из UDP-датаграммы через параметры сокета.
| Поле | Размер | Назначение |
|---|---|---|
| seq_num | 4 байта | Номер смещения байта (byte-offset), а не номер сегмента. Позволяет корректно склеивать данные при乱序 (нарушении порядка) доставки. |
| ack_num | 4 байта | Номер следующего ожидаемого байта от отправителя. Аналог подтверждения в TCP. |
| flags | 1 байт | Флаги управления: SYN, ACK, FIN, RST. Остальные 4 бита зарезервированы. |
| checksum | 2 байта | Контрольная сумма для проверки целостности данных. Реализована собственная, так как в UDP для IPv4 она опциональна. |
| Padding | 1 байт | Выравнивание структуры по 4-байтовой границе (заполнено нулями). |
Ключевые механизмы надежности
Для обеспечения надежности поверх UDP были реализованы следующие механизмы, заимствованные из архитектуры TCP:
- Нумерация по смещению байтов: Вместо нумерации пакетов (1, 2, 3...) используется нумерация байтов потока. Если первый сегмент содержит 1400 байт, следующий имеет
seq_num = 1400. Это упрощает обработку фрагментов разного размера. - Флаг FIN: Используется для корректного завершения сессии. Получатель, увидев флаг FIN, закрывает файл и освобождает ресурсы, решая проблему «висящих» соединений.
- Собственная контрольная сумма: Несмотря на наличие чексуммы в UDP, авторы реализовали свою, так как согласно RFC 768, нулевая чексумма в UDP означает отсутствие проверки, что небезопасно для критичных данных.
Результаты тестирования
Протокол P7 прошел стресс-тестирование в условиях, имитирующих нестабильную сеть. Ключевые результаты:
- Потери пакетов: Сеть генерировала 30% потерь пакетов.
- Целостность данных: Данные были переданы байт-в-байт без искажений.
- Производительность: При высоких потерях сеть на базе P7 показала неожиданные результаты по скорости, что связано с эффективной работой механизмов повторной передачи и скользящего окна, настроенных под конкретные условия тестирования.
Проект демонстрирует, что реализация надежного транспорта поверх UDP возможна и может быть эффективной в специфических сценариях, где требуется полный контроль над сетевым стеком, минуя ограничения ядра Linux.
Источник: Habr ↗
