реализовать ACK через UDP? - PullRequest
8 голосов
/ 04 октября 2009

У нас есть система (встроенная в C), которая осуществляет связь по UDP. Недавно мы обнаружили необходимость гарантировать доставку пакетов. Мой вопрос: что было бы минимальным дополнением к системе на основе UDP для обеспечения доставки с использованием пакетов ack? Кроме того, в идеале, без необходимости манипулировать заголовками пакетов. У нас есть контроль на уровне приложений для пакетов, включая порядковые номера и флаги ack / nack. Мне интересно, если это потерянное дело, и все, что мы пытаемся сделать, будет в основном ошибочной и сломанной версией TCP. По сути, есть ли минимальное улучшение, которое мы можем сделать для достижения гарантированной доставки (нам не нужны многие функции TCP, такие как контроль перегрузки и т. Д.). Спасибо!

Ответы [ 5 ]

9 голосов
/ 05 октября 2009

TCP переплетается с 3 сервисами, которые могут иметь отношение (хорошо, TCP делает намного больше, но я собираюсь поговорить только о 3).

  1. Доставка по заказу
  2. Надежная доставка
  3. Контроль потока

Вы только что сказали, что вам не нужно управление потоком, поэтому я даже не буду об этом говорить (как вы будете рекламировать размер окна и т. Д., За исключением того, что вам, вероятно, понадобится окно. Я получу к нему.)

Вы сказали, что вам нужна надежная доставка. Это не так сложно - вы используете ACK, чтобы показать, что отправитель получил пакет. Базовая надежная доставка выглядит так:

  1. Отправитель отправляет пакет
  2. Получатель получает пакет, а затем отправляет подтверждение
  3. Если отправитель не получает подтверждение (посредством таймера), он повторно отправляет пакет.

Эти три шага не решают эти проблемы:

  1. Что делать, если ACK теряется?
  2. Что делать, если пакеты приходят не в порядке?

Итак, для вашего приложения вы сказали, что вам нужна только надежная доставка - но ничего не сказали о том, что они нужны для заказа. Это повлияет на способ реализации вашего протокола.

(пример, в котором порядок не имеет значения: вы копируете записи сотрудников с одного компьютера на другой. Не имеет значения, получена ли запись Алисы раньше, чем Боб, до тех пор, пока оба получат).

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

Ваш отправитель может отслеживать неподтвержденные пакеты. Таким образом, если он отправляет 3, 4, 5 и 6 и не получает ACK для 3 и 4, то отправитель знает, что ему нужно повторить передачу. (Хотя отправитель не знает, были ли пакеты 3 и 4 большими или их ACK были потеряны. В любом случае, мы должны повторить передачу.)

Но тогда ваш отправитель может сделать кумулятивные ACK - поэтому в приведенном выше примере он получит подтверждение № 6 только при получении 3, 4 и 5. Это означает, что получатель отбросит пакет 6 если бы он не получил раньше. Если ваша сеть очень надежна, то это не плохой вариант.

Протоколы, описанные выше, однако, имеют окно - то есть, сколько пакетов отправитель отправляет одновременно? Это означает, что вам нужно какое-то окно, но не для управления потоком. Как вы будете передавать размеры окна?

Вы можете сделать это без окна, используя постоянный размер окна или сделав что-то вроде остановки и ожидания. Первый может быть лучшим вариантом.

В любом случае, я не ответил прямо на ваш вопрос, но я надеюсь, что указал на некоторые вещи, которые стоит учитывать при разработке этого. Задача «надежного переноса» без элементов управления потоком (например, окон) и без учета порядка очень трудна! (Дайте мне знать, если я расскажу больше об этом материале!)

Удачи!

5 голосов
/ 04 октября 2009

Взгляните на Главу 8 и Главу 20 Сетевого программирования UNIX Стивена, том 1 . Он охватывает ряд различных подходов. Раздел 20.5 «Добавление надежности в приложение UDP», вероятно, наиболее интересен для вас.

4 голосов
/ 04 октября 2009

У меня есть вопрос, работающий здесь , который собирает ответы на вопросы "Что вы используете, когда вам нужен надежный UDP". Ответы, возможно, гораздо больше, чем вы хотите или нуждаетесь, но вы можете взглянуть на некоторые протоколы, которые были построены на UDP, и получить только ту часть ACK, которая вам нужна.

Из моей работы с протоколом ENet (надежным протоколом UDP) я ожидаю, что вам нужен порядковый номер в каждой дейтаграмме UDP, способ отправки ACK для полученных вами дейтаграмм, способ удержания датаграммы, которые вы отправили, пока не получите ACK для них, или они не истекут, и способ синхронизации повторной отправки дейтаграмм, для которых вы еще не получили ACK ... Я бы также добавил общее время ожидания, когда вы решите, что вы никогда не собираетесь доставлять конкретную дейтаграмму и, я полагаю, обратный вызов на уровень вашего приложения, чтобы сообщить ему об этом сбое доставки ...

0 голосов
/ 03 февраля 2016

Лучший способ реализовать ack - это сделать это на уровне приложений. CoAP является примером протокола приложения, который работает на UDP, но обеспечивает надежную передачу данных. Он сохраняет идентификатор сообщения для всех сообщений Confirmable (CON) и отправляет получателю отправку пакета подтверждения с тем же идентификатором сообщения. Все поля ack и id сообщения хранятся на уровне прикладного уровня. Поэтому, если отправитель не получает пакет Ack с отправленным им идентификатором сообщения, он повторно передает этот пакет. Разработчик приложения может изменить протокол в соответствии с потребностями, необходимыми для надежной передачи данных.

0 голосов
/ 04 октября 2009

Сложная проблема. Я бы сказал, что вы не сможете добиться надежности TCP. Тем не менее, я понимаю, что иногда вам нужно иметь надежный UDP.

Форум Gamedev

RUDP (чуть более хардкорный)

Старая тема о надежном UDP

...