Является ли хорошей практикой дублировать UDP пакеты для минимизации вероятности их потерь?
Например, клиент шлет серверу координаты мыши, по которым выполняется нажатие. Клиенту очевидно не понравится, если сервер просто проигнорирует его действие, из-за того, что пакет был утерян. Я подумал, что можно легко решить эту проблему, добавляя в начало пакета номер пакета (случайное, соответственно, практически по-любому уникальное, большое число) и отправляя сразу несколько пакетов с одинаковым номером. В таком случае, получая пакет, сервер будет смотреть в какой-нибудь хеш таблице номер полученного пакета, и, если его там нет, то обрабатывать его и помечать этот номер как обработанный. Есть ли какие-то подводные у такого решения? Где-нибудь так делают?
Ответы (1 шт):
То что Вы описали - так фактически работает протокол SIP
, потому что зачастую он идёт как раз поверх UDP. Отвечу на его примере, так как много работал с ним, но такие принципы могут использоваться и в схожих протоколах, работающих по UDP.
Поскольку UDP не гарантирует доставку пакета данных (в отличие от TCP), то механизмы обеспечения доставки обеспечивает сам SIP. Однако, сама по себе передача данных по UDP не означает обязательность реализации на протоколе прикладного уровня механизмов защиты от потерь. SIP это сигнальный протокол, благодаря которому устанавливается сеанс связи - в нём важен каждый запрос и ответ, так как без соблюдения полной процедуры связь не установится. Ваша ситуация по описанию схожа с SIP - требуется обеспечить доставку информации о каждом нажатии мыши.
А вот в протоколе RTP
, который используется для передачи медиа, контроля доставки пакетов нет. При передаче голоса в режиме реального времени (SIP и RTP используются для звонков) разумнее пожертвовать некоторыми потерянными пакетами, чем пытаться контролировать каждый. Отдельный RTP пакет обычно несет информацию о 20-30 мс аудио (зависит от параметра ptime
) - потерю одного-двух пакетов из сотни человек в разговоре не заметит. Нормой считаются потери до 5% пакетов и задержки их передачи от абонента к абоненту до 150 мс - до этих значений речь ощущается нормальной. Такой подход подошел бы Вам, если бы требовалось, например, реализовать стриминг экрана без возможности взаимодействия с ним - здесь просто должна постоянно обновляться картинка, и ценности прошедшие кадры уже не имеют.
Говоря о механизмах обеспечения доставки, действительно SIP-оборудование зачастую отсылает сразу 2-3 пакета с одинаковым запросом (например, INVITE). И в каждом пакете есть заголовок CSeq
(порядковый номер запроса в рамках сессии между абонентами) и метка branch
в заголовке Via
(идентификатор транзакции). Принимающая сторона видит, что практически в один момент пришли одинаковые пакеты и учитывает их как один запрос, а не обрабатывает как 3 разных. В такой ситуации если какой-то из запросов не дошёл, то доставку обеспечат оставшиеся пакеты.
Также, применительно к запросу INVITE, SIP сам реализует процесс трёх рукопожатий (как в TCP):
INVITE (запрос) -> 200 OK (ответ) -> ACK (подтверждение получения ответа)
Если на INVITE на приходит ответ (200 OK или иной) за определенное время, то устройство будет повторно высылать недоставленный запрос (до истечения предельного таймаута попытки установления связи).