Что вы используете, когда вам нужен надежный UDP?

Если у вас есть ситуация, когда TCP-соединение потенциально слишком медленно, а UDP-соединение потенциально слишком ненадежно, что вы используете? Существуют различные стандартные надежные протоколы UDP, какой опыт у вас есть с ними?

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

Я заинтересован в различных параметры здесь, из которых TCP находится на одном конце шкалы, а UDP-на другом. Различные надежные варианты UDP доступны и каждый приносит некоторые элементы TCP к UDP.

Я знаю, что часто TCP является правильным выбором, но наличие списка альтернатив часто полезно, чтобы помочь прийти к такому выводу. Такие вещи, как Enet, RUDP и т. д., которые построены на UDP, имеют различные плюсы и минусы, вы их использовали, каковы ваши впечатления?

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

13 ответов


трудно ответить на этот вопрос без дополнительной информации о домене проблемы. Например, какой объем данных вы используете? Как часто? Какова природа данных? (напр. является ли это уникальным, one off data? Или это поток выборочных данных? так далее.) Для какой платформы вы разрабатываете? (напр. рабочий стол / сервер / встроенный) Чтобы определить, что вы подразумеваете под "слишком медленным", какой сетевой носитель вы используете?

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

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

но если вы не можете терпеть потерю одного пакета, тогда вам придется начать вводить типы методов для надежности, которые уже есть у tcp. И, не вкладывая разумный объем работы, вы можете обнаружить, что начинаете строить эти элементы в решение пользовательского пространства со всеми присущими ему проблемами скорости.


насчет протокол SCTP. Это стандартный протокол IETF (RFC 4960)

Он имеет возможность ломать которая смогла помочь для скорости.

обновление: a сравнение между TCP и SCTP показывает, что производительность сопоставима, если не могут использоваться два интерфейса.

обновление: a хорошая вступительная статья.


ENET - http://enet.bespin.org/

Я работал с ENET в качестве надежного протокола UDP и написал асинхронную версию сокетов для моего клиента, который использует ее на своих серверах. Он работает довольно хорошо, но мне не нравятся накладные расходы, которые одноранговый пинг добавляет к другим бездействующим соединениям; когда у вас много соединений, все из них регулярно-это много занятой работы.

ENET дает вам возможность отправить несколько каналов данных и для данных, отправляемых быть ненадежными, надежными и последовательными. Он также включает вышеупомянутый одноранговый пинг, который действует как keep alive.


У нас есть некоторые клиенты оборонной промышленности, которые используют UDT (передача данных на основе UDP) (см.http://udt.sourceforge.net/) и очень довольны этим. Я вижу, что у этого есть дружественная лицензия BSD.


RUDP - Надежный Протокол Дейтаграммы Пользователя

обеспечивает:

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

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


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

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

есть легкая середина. алгоритм Нэгла является частью TCP, которая помогает гарантировать, что отправитель не перегружает получателя большого потока данных, что приводит к перегрузке и потере пакета.

Если вам нужна надежная доставка по порядку TCP, а также быстрая реакция UDP, и вам не нужно беспокоиться о перегрузке от отправки больших потоков данных, вы можете отключить алгоритм Нэгла:

int opt = -1;
if (setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(opt)))
  printf("Error disabling Nagle's algorithm.\n");

любой, кто решает, что приведенный выше список недостаточно и что они хотят разработать свой собственный надежный UDP, определенно должен взглянуть на спецификацию Google QUIC, поскольку это охватывает множество сложных угловых случаев и потенциальных атак отказа в обслуживании. Я еще не играл с реализацией этого, и вам может не понадобиться все, что он предоставляет, но документ стоит прочитать, прежде чем приступать к новому "надежному" дизайну UDP.

хорошая отправная точка для QUIC-это здесь, в блоге Chromium.

текущий проектный документ QUIC можно найти здесь.


Если у вас есть ситуация, когда TCP-соединение потенциально слишком медленно, а UDP-соединение потенциально слишком ненадежно, что вы используете? Существуют различные стандартные надежные протоколы UDP, какой опыт у вас есть с ними?

ключевое слово в вашем предложении - "потенциально". Я думаю, вам действительно нужно доказать себе, что TCP на самом деле слишком медленный для ваших нужд, если вам нужна надежность в вашем протоколе.

Если вы хотите получить надежность из UDP, тогда вы в основном будете повторно внедрять некоторые функции TCP поверх UDP, которые, вероятно, сделают вещи медленнее, чем просто использование TCP в первую очередь.


протокол DCCP, стандартизированный в RFC 4340, "протокол управления перегрузкой дейтаграммы" может быть тем, что вы ищете.

кажется реализовано в Linux.


может быть RFC 5405, "unicast UDP рекомендации по использованию для дизайнеров приложений" будет полезно для вас.


вы рассматривали возможность сжатия данных ?

Как указано выше, нам не хватает информации о точной природе вашей проблемы, но сжатие данных для их транспортировки может помочь.


RUDP. Многие серверы сокетов для игр реализуют нечто подобное.


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