UDP по-прежнему лучше, чем TCP, для игр с большим объемом данных в реальном времени?

71

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

Большинству статей посвящено несколько лет, и, поскольку ~ 80% всех данных, передаваемых в Интернете, - это TCP, для TCP должна быть проведена большая оптимизация.

Это заставляет меня задуматься: по-прежнему ли UDP превосходит скорость и задержку? Могли ли недавние оптимизации TCP сделать TCP работать лучше, чем UDP?

KaareZ
источник
25
С UDP нет никакой гарантии, что ваши пакеты будут получены или даже заказаны, что само по себе делает UDP быстрее, чем TCP.
Натан
4
@KaareZ что ты имеешь в виду быстрее реализовать?
Натан
2
@nathan Разработать приложение с помощью TCP проще, чем UDP. Я хочу знать, все ли оптимизации TCP сделали TCP лучшим вариантом с точки зрения производительности.
KaareZ
3
@KaareZ Я не эксперт, но давайте подумаем. Как TCP может быть лучше с точки зрения производительности и при этом оставаться надежным протоколом? У тебя не может быть всего. TCP сделан для надежности. Реальный вопрос в том, почему вы хотите использовать TCP в своей игре?
Натан
7
UDP лучше, чем TCP, если и только если вы способны (= опытный программист низкоуровневого сетевого взаимодействия) эффективно реализовать только те функции TCP, которые вам нужны. Отбрасывание ненужных функций TCP для производительности.
Wondra

Ответы:

119

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

TCP создает абстракцию, в которой поступают все сетевые пакеты, и они приходят в точном порядке, в котором они были отправлены. Чтобы реализовать такую ​​абстракцию на канале с потерями, он должен реализовать повторные передачи и тайм-ауты, которые занимают время. Если вы отправите 2 обновления по TCP, и пакет первого обновления будет потерян, второе обновление не будет отображаться до тех пор, пока:

  1. Утрата первого обновления обнаружена.
  2. Повторная передача первого обновления запрашивается.
  3. повторная передача прибыла и была обработана.

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

Это требует, чтобы вы отправляли правильный тип данных и разрабатывали свое общение таким образом, чтобы потеря данных была приемлемой.

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

РЕДАКТИРОВАТЬ - Добавление некоторой дополнительной информации для включения / адресации некоторых комментариев:

Как правило, уровень потери пакетов в Ethernet очень низок, но он становится намного выше, если задействован WiFi или если пользователь выполняет загрузку / загрузку. Давайте предположим, что у нас совершенно равномерная потеря пакетов 0,01% (в одну сторону, а не в оба конца). На шутере от первого лица клиенты должны отправлять обновления всякий раз, когда что-то происходит, например, когда курсор мыши поворачивает плеер, что происходит примерно 20 раз в секунду. Они также могут отправлять обновления по кадрам или с фиксированным интервалом, который будет составлять 60-120 обновлений в секунду. Поскольку эти обновления отправляются в разное время, они будут / должны отправляться в одном пакете за обновление. В игре на 16 игроков все 16 игроков отправляют эти 20-120 пакетов в секунду на сервер, в результате чего получается 320-1920 пакетов в секунду. С нашей скоростью потери пакетов 0,01% мы ожидаем потерять пакет каждые 5,2-31,25 секунды.

На каждый пакет, который мы получаем после потерянного пакета, мы отправляем DupAck, а после 3-го DupAck отправитель повторно передает потерянный пакет . Таким образом, время, которое требуется TCP для инициации повторной передачи, составляет 3 пакета плюс время, необходимое для того, чтобы последний DupAck пришел к отправителю. Затем нам нужно дождаться прибытия ретрансляции, поэтому в общей сложности мы ожидаем 3 пакета + 1 задержка туда и обратно. Задержка передачи в оба конца обычно составляет 0-1 мс в локальной сети и 50-200 мс в Интернете. 3 пакета обычно приходят через 25 мс, если мы отправляем 120 пакетов в секунду, и через 150 мс, если мы отправляем 20 пакетов в секунду.

Напротив, в случае UDP мы восстанавливаемся из потерянного пакета, как только получаем следующий пакет, поэтому мы теряем 8,3 мс, если отправляем 120 пакетов в секунду, и 50 мс, если отправляем 20 пакетов в секунду.

С TCP все становится еще сложнее, если мы также должны учитывать Nagle (если разработчик забывает отключить объединение отправки или не может отключить задержанный ACK ), предотвращение перегрузки сети или достаточно большая потеря пакетов, что мы должны учитывать несколько потери пакетов (включая потерянные Ack и DupAck). С помощью UDP мы можем легко написать более быстрый код, потому что нам просто не важно быть хорошим сетевым гражданином, как это делает TCP.

Питер
источник
Примечание: UDP может транслировать локальную сеть (возможное преимущество), и поскольку Vista требует, чтобы администратор запускал сервер / широковещательную передачу по UDP (недостаток) (UAC / брандмауэр, как правило, не в состоянии сообщить, что требуется действие пользователя).
PTwr
7
«Если вы отправляете 2 обновления по TCP, и пакет первого обновления теряется» Правда, но каковы шансы на это? По словам Пингмана : «Потеря пакетов более чем на 2% за определенный период времени является сильным индикатором проблем».
Мукахо
30
@Peter, вы забываете, что в TCP каждый отброшенный пакет останавливается каждый последующий пакет. При пинге 100 мс может пройти 300-500 мс, прежде чем этот пакет будет повторно передан и получен, так что это 6-10 пакетов, которые останавливаются каждые 33 секунды. Это определенно будет заметно в подобном землетрясению FPS.
BlueRaja - Дэнни Пфлугхофт
12
Во многих реализациях TCP первый тайм-аут после пропущенного подтверждения будет занимать целую секунду. Это долго . Если пакеты малы, UDP может легко сгладить пропущенную передачу или две, просто включив в каждый пакет данные из двух последних обновлений, чтобы приложение получило необходимые данные, прежде чем отправитель или получатель узнают, что первый пакет пропал.
суперкат
23
В такой игре, как Quake, потеря первого пакета не имеет значения. В FAR меньше времени, которое потребовалось бы для обнаружения потери и повторной передачи первого пакета, вы должны были уже передать второй пакет, который в любом случае делает первый устаревшим. Это та же самая причина, по которой многие приложения для передачи голоса и видео в реальном времени также используют UDP. Если пакет будет отброшен, вы скорее просто потеряете 0,02 секунды звука, чем задержите весь поток на целую секунду или более. То же самое , как правило , правда в режиме реального времени игры, как вы хотите знать , где объект находится в настоящее время , не 1,5 секунды назад.
Рейраб
19

Мы согласны с тем, что TCP и UDP являются протоколами, основанными на IP , не так ли? IP определяет, как сообщения доставляются через Интернет, но ничего не касается структуры, формата сообщений. Здесь идут протоколы TCP и UDP. Они используют свойства IP, но позволяют программисту сосредоточиться на обмене сообщениями, не беспокоясь о нижних уровнях сетевого взаимодействия. И это здорово, потому что иметь дело с аналоговыми сигналами в проводах напрямую было бы болезненно.

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

  • С другой стороны, UDP - это протокол, ориентированный на управление пользователями. При использовании UDP для отправки наших дейтаграмм , мы не можем быть уверены, что датаграмма когда-нибудь прибудет в пункт назначения или нет (и здесь мы подразумеваем математическую уверенность: когда мы отправляем пакет, он, вероятно, прибудет, но мы не можем быть уверены, что 100%). Кроме того, когда пакет потерян, он не будет ни обнаружен, ни отправлен снова.

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

НО , смотрите дальше. Единственное преимущество, которое дает нам UDP, - это его скорость, и это единственное, чего мы действительно хотим. Пакет UDP просто создается, проверяется и отправляется без каких-либо определенных элементов управления, потому что именно так работает протокол UDP. Пакет TCP должен быть обработан, помечен, проверен на наличие сумм, и когда он прибывает, ACK отправляется обратно, чтобы сообщить отправителю «пакет x здесь, продолжайте идти» , и когда этот сигнал не отправляется, это означает, что такой пакет x должен быть отправлен очередной раз.

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

Да, но не только. UDP в значительной степени предпочтительнее, чем TCP, главным образом потому, что его высокая скорость является идеальной для обработки больших объемов данных и управления ими. Это происходит, когда, предполагая, что такая видеоигра работает на детерминированном шаге (то, что происходит на сервере, одинаково реплицируется на любом клиенте независимо от задержки в сети), пакет обновления теряется и никогда не достигает своего места назначения. TCP будет повторно отправлять такой пакет, и следующие пакеты будут отброшены, поскольку поступают не по порядку, а затем повторно отправляются после потерянного. UDP гораздо более терпим в этом сценарии: он не будет заботиться об этом пакете, потому что приходят новые обновления. Потерянное обновление не отображается, вместо этого физика игры интерполируется по используемому методу интеграции и получению последнего обновления.

TCP вызывает дрожание, когда задержка достаточно высока, UDP не:

<video style="min-width: 100% height: auto" autoplay="" preload="auto" loop="true"><source src="https://gafferongames.com/videos/deterministic_lockstep_tcp_250ms_5pc.mp4" type="video/mp4"><source src="http://173.255.195.190/cubes_deterministic_lockstep_tcp_250ms_5pc.webm" type="video/webm">Your browser does not support the video tag.</video>

Это заставляет меня задаться вопросом, является ли UDP все еще лучше с точки зрения скорости и задержки.

Ну да, так и будет долго . Вы можете узнать больше о TCP против UDP здесь .

liggiorgio
источник
8
TCP использует потоки байтов, а не дейтаграммы. UDP использует дейтаграммы. Хорошие реализации TCP будут сохранять пакеты, которые поступают не по порядку, но содержимое пакета не может быть предоставлено приложению до тех пор, пока не будут получены все предыдущие пакеты. Таким образом, если один пакет потерян, отправителю может не понадобиться повторно передавать все, что следует за потерянным пакетом, но принимающее приложение не увидит ничего за потерянным пакетом, пока этот пакет не будет повторно передан (после чего приложение мгновенно увидит содержимое этого пакета). пакет и те, что после).
суперкат
@supercat К сожалению, TCP не может точно сказать отправителю, какие именно пакеты он отправил и не получил. У него есть только механизм для «Я получил все байты через x порядковый номер». Если отправитель повторно передает пакеты, которые получатель уже получил, он просто игнорирует копии.
Рейраб
@reirab: Я думал, что есть некоторые современные расширения, включающие эту функцию, хотя даже без этого я думаю, что реализация, которая отправила данные до байта # 1 050 000, но получила подтверждения только для данных до 1 000 000, через секунду не услышав Любое подтверждение чего-либо после 1 000 000, начните с отправки блока данных от 1 000 000 до 1 000 500 или около того, а затем ожидая ответа. Если он получает подтверждение для данных до 1 500 500, он может затем повторно передать больше данных; если он получает подтверждение для данных до 1 050 000, он может пропустить повторные передачи.
суперкат
1
@Giorgio IP ничего не указывает на аналоговые сигналы. Это делается на физическом уровне. IP работает на два уровня выше, чем на сетевом уровне. IP не заботит, идут ли биты по оптоволоконному кабелю, по спутниковой линии или модему 14,4 кбит / с. UDP и TCP являются уровнем выше IP, на транспортном уровне. Кроме того, как говорит supercat, TCP представляет потоковый интерфейс приложения, а не интерфейс дейтаграмм, как UDP.
Рейраб
@supercat Хмм ... вы можете быть правы насчет современных расширений, хотя они, конечно, не являются частью оригинального стандарта TCP. У ACK просто есть порядковый номер. Я бы предположил, что реализация TCP обычно начинает ретрансляцию всего окна отправки, если пакет отбрасывается, а не ожидает около RTT для каждого пакета. Это добавило бы огромную задержку, если несколько последовательных пакетов были потеряны для очень небольшого усиления.
Рейраб
9

TCP <- протокол управления передачей. Это сделано для контроля передачи.

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

  • Получатель обнаруживает отсутствующий пакет, сообщает отправителю замедлить работу (на некоторое время уменьшить скорость вдвое).
  • Получатель обнаруживает неправильный порядок входящих пакетов (возможно, они использовали разные сетевые пути), сообщает отправителю замедлить работу - и, между прочим, получатель не будет принимать дополнительные пакеты, пока не поступит отсутствующий. Для этого требуется время.
  • Отправитель обнаруживает перегрузку сети (например, медленное время туда и обратно), добавляет задержку.
  • Получатель не может поспевать за скоростью (входной буфер переполняется), просит отправителя добавить задержку (управление потоком).
  • Среди приемников есть один медленный приемник (ублюдок с высоким пингом, crybaby, как их называют), в домохозяйстве добавлена ​​задержка (может быть).

Дополнительно

  • Алгоритм Nagle может удерживать данные отправителя в ожидании до тех пор, пока больше не будет отправлено (для более эффективного использования фреймов данных). Критические по времени данные задерживаются.
  • Я считаю, что обычные домашние маршрутизаторы с wlan могут делать умные вещи (замедляться), чтобы сгладить пропускную способность TCP между несколькими клиентами (узким местом является интерфейс wlan, даже если игра его не использует). Относится к вещанию / многоадресной передаче, т.е. «другие» данные могут снизить пропускную способность TCP.
  • TCP ACK знает все, что не нужно для игровой среды. Нет смысла ACKing каждое обновление физики. Достаточно для подтверждения, например, один раз в секунду или аналогичным образом. Если клиент (или сервер) молчит дольше, то пора реагировать.

Несмотря на это, TCP обеспечивает самый высокий показатель для (общих передаваемых данных) / (общего потребляемого времени). Просто это не происходит именно тогда, когда вы хотите, чтобы это произошло.

UDP не делает ничего из этого. Он стреляет по вашей воле, просто никто не может ожидать, что он будет поражать каждый раз - если цель должна объявить, что «вы не стреляли в течение долгого времени, почему?». Можно по-прежнему создавать собственные настраиваемые пакеты ACK, помещать несколько записей в один пакет и т. Д. А также важно контролировать обход NAT. UDP, безусловно, подходит для игр с низкой задержкой.

Штормград
источник
1
Примечание: алгоритм Nagle может быть отключен, например, для Linux .
Мукахо
Nagle может работать против (и его можно обойти, установив для каждого пакета «push» приложением), в то время как Delayed Ack работает в пользу TCP, что позволяет отправителю помещать больше байтов в провод, пока окно отправки не будет заполнено (в идеале, большим так как приемный буфер находится на другой стороне) независимо от того, был ли замечен ack.
Джефф Меден
4
Это протокол управления передачей .
ysdx
1
Введите эти слова миллион раз ... THX - исправлено.
Штормград
3

Вы можете сравнить первую диаграмму RFC 768 (UDP) с первой диаграммой RFCP 793 (TCP), стр. 15 .

Оба показывают 16 битов для «порта источника», а затем 16 битов для «порта назначения». Оба показывают 16 битов для «контрольной суммы». Согласно RFC 768, процедура «контрольной суммы UDP» такая же, как и в TCP ».

В то время как длина UDP включает в себя подробности диаграммы UDP, длина TCP является частью «96-битного псевдо заголовка», описанного на стр. 15 и 16.

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

Другая причина в том, что «трехстороннее рукопожатие» TCP означает, что отправитель должен ждать ответа. Это требование вводит дополнительные издержки, которые UDP не обрабатывает. Есть причина, по которой большинство ваших интернет-коммуникаций начинаются с UDP-соединения. Основной DNS использует UDP, потому что запрос и ответ могут быть выполнены за меньшее количество шагов, чем процесс «трехстороннего рукопожатия» в TCP. Функция отслеживания потерянных пакетов в TCP довольно неинтересна, потому что компьютер может просто сделать новый запрос, а не пытаться сообщить удаленной системе о наличии невыполненного предварительного запроса.

TOOGAM
источник
Хотя аннотации на английском языке (как видно из некоторых других ответов) хороши, просто иметь некоторые точные и точные описания может быть проще всего.
TOOGAM
Вы имеете в виду 16 бит, а не байты!
Jcaron
О, глупый я. это пример того, почему технически точные ответы хороши; их легко идентифицировать ошибки и увидеть правильную информацию. Я исправил ответ. Спасибо @jcaron
TOOGAM
2

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

  1. Держите сеанс TCP открытым, и когда бомба должна взорваться, отправьте сообщение TCP всем игрокам (если возможно, см. Ниже)
  2. Прослушивайте UDP-порт, и когда бомба должна сработать, отправьте UDP-сообщение всем игрокам, независимо от их состояния соединения.

Предполагая, что не было никакого обновления, необходимого прямо перед ним, время, когда это единственное обновление прибывает в 1 против 2, не будет очень отличаться. Это одна поездка от сервера к клиенту. Но, скажем, вместо того, чтобы просто взорвать бомбу, вы пытаетесь постоянно передавать действия кого-то, бегущего через лабиринт; ткачество, уклонение, стрельба и т. д. В случае UDP каждое действие будет отправлено в дейтаграмме, как только это произойдет. В случае TCP каждое действие будет отправлено в пакете, только если серверу разрешено отправлять. Что говорит, что разрешено отправлять? Наличие места в окне TCP (при условии, что задержка подтверждения активна), так что сообщение может быть передано по проводам. Если нет, он должен дождаться подтверждения получения от клиента перед отправкой.

Как долго это слишком долго? Когда разработка многопользовательских шутеров от первого лица пошла на спад, в конце 90-х и начале 2000-х годов соединения с малой задержкой не были обычным явлением. Модемный модем будет иметь типичную одностороннюю задержку 180 мс. Ожидать ack перед отправкой другого обновления, фактически удваивая это время до 360 мс, было больно; Даже начинающие пользователи могут почувствовать разницу. Когда широкополосные соединения завоевали популярность, они значительно снизили задержку, но она все еще сохранялась, когда пропускная способность была в дефиците (довольно часто в некоторых областях). Таким образом, предпочтение минимальной возможной задержки сохранялось.

Современные домашние соединения и соединения изменили это до такой степени, что региональная задержка, даже в перегруженное время суток, находится в диапазоне 15 мс или ниже. Выбор TCP вместо UDP был бы невидим в большинстве случаев, так как задержка «достаточно низкая». Тем не менее, все еще существует тенденция приоритета UDP по сравнению с TCP, учитывая его историю как протокола с низкой задержкой. Таким образом, на данный момент (и, возможно, в будущем) UDP будет предпочтительным для связи в реальном времени.

Джефф Меден
источник
Задержка будет достаточно низкой, за исключением того, что по умолчанию записи TCP отправляются только тогда, когда происходит перезапись данных для записи через определенный порог или время ожидания (обычно 200-1000 мс). Если вам нужен TCP в системе с низкой задержкой и небольшой пропускной способностью, вы должны отключить эту функцию и убедиться, что вы не пишете отдельные байты все время (например, вы больше не рассматриваете поток TCP как поток и притворяетесь, что вы Разбираемся с отдельными сообщениями). Вам не нужно ждать ACK, если ваши буферы не заполнены, что вряд ли произойдет в типичной игре в реальном времени.
Луаан
1
@Luaan Enter: флаг TCP PSH. Когда приложение передает его в стек, пакет отправляется немедленно, без ожидания дополнительных данных. Многие приложения используют это успешно (например, telnet и ssh).
Джефф Меден
2

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

Ваши предположения неверны. TCP и UDP отличаются прежде всего тем, какую модель они представляют (ненадежные дейтаграммы в сравнении с порядком надежного виртуального потока).

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

При наличии потери пакетов эти два значения различаются по задержке, но только в этом состоянии. В противном случае TCP имеет такую ​​же низкую задержку, как и UDP (дайте или возьмите, может быть, несколько десятков наносекунд, потому что в сетевом стеке немного больше логики, но это довольно пренебрежимо мало).
Есть небольшая разница в размере заголовка, так что технически, больше байтов должно пройти по проводам на последовательных линиях, но это тоже довольно несущественно. Это действительно имеет значение только для массовых переводов, а затем разница составляет около 0,5%. Большинство людей с домашним доступом к DSL-Интернету направляют весь свой трафик через ATM, что увеличивает накладные расходы протокола на 10% (5 управляющих байтов для 48 байт полезной нагрузки плюс частичные кадры), и никто даже не замечает.

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

Игры обычно используют UDP не потому, что он превосходит один из вышеупомянутых способов - это не так - или потому что вы можете уменьшить джиттер на полмисекунды, реализуя надежность без упорядоченности, а потому, что игры (во многом как IP-телефония) часто содержат много очень изменчивых данных, таких как, например, обновления позиций.
Эти изменчивые данные регулярно и быстро устаревают как по прошествии времени, так и по следующей поступающей дейтаграмме. Что означает не больше и не меньше, чем то, что вы на самом деле не слишком заботитесь о том, чтобы быть на 100% надежными (или в порядке).

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

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

Обратите внимание на то, что потеря пакетов является нормальным условием. Несмотря на то, что IP, как правило, «довольно надежный», иногда могут быть отброшены пакеты, и это произойдет . Хотя потеря пакетов обычно происходит в редких случаях (<1% здесь), это не что-то экстраординарное или теоретическое или указание на то, что что-то сломано. Это совершенно нормально. Например,
каждая массовая передача TCP обязательно будет включать потерянные пакеты (именно так работает контроль перегрузки).

Damon
источник
2

В MPG с высокой пропускной способностью вас не волнует, пропустили ли вы пакет, дающий вам местоположение и здоровье монстра # 425, потому что вы получите еще одно обновление через несколько секунд. Это и пример, где UDP заставляет TCP выглядеть глупо, заставляя вас ждать мгновенно устаревших данных.

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

Вот простое описание того, что происходит.

UDP - Изолировать кусок O'data.
Сделай пакет.
Инкапсулировать в IP.
Отправим его.

TCP - изолировать поток O'data.
Сделайте пакет с начала потока.
Инкапсулировать в IP.
Ждите места в окне TCP.
Отправим его.
Продолжайте пересылку до получения квитанции или тайм-аута.
Оставайтесь в окне TCP до получения квитанции или тайм-аута.

Доставка означает, что она прошла через местный сетевой адаптер, не более.

Прием TCP-приема гарантирует получение данных и освобождает место в окне для следующего пакета.

Повторная отправка (немного) увеличивает вероятность возможного получения.

TCP-пакеты собираются на другой стороне в виде упорядоченного потока данных. Пакеты UPD принимаются как отдельные пакеты. Протокол не сохраняет порядок.

TCP хорош для передачи необходимых данных и больших упорядоченных объемов данных. TCP предоставляет уведомление о постоянном сбое. TCP самодросселируется через забитые трубы (ссылка: окно). TCP имеет рукопожатия для замедления инициализации. TCP требует «соединения» перед передачей.

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

Я разработал и написал коммерческую утилиту для многоадресной передачи файлов UDP. Я работал над IP-стеками. Это просто основы, без мелочей. Объяснение «сокетов, MTU и других забавных игрушек» было немного за пределами того, что было бы полезно для этого вопроса.

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

dusc2don
источник
3
Ваше мнение об "устаревших" данных является хорошим. TCP хорош для данных «лучше поздно, чем никогда», но UDP хорош для данных, которые будут полезны, если он быстро достигнет пункта назначения, но бесполезны, если этого не произойдет.
суперкат
1

Все ли оптимизированные по TCP маршрутизаторы позволили TCP работать лучше, чем UDP?

Еще один вопрос: означает ли «интенсивный обмен данными», что вы будете часто загружать сцены?

Если да, вам может понадобиться интенсивно отправлять большие фрагменты данных (> 1 Кб), в которых TCP может быть гораздо более эффективным, поскольку, особенно на стороне сервера, сетевые адаптеры будут обеспечивать различные нагрузки, которые имеют одинаковую серию циклов. Приложение пользовательского пространства может выдавать большие записи по протоколу TCP, тогда как в UDP попытка отправки более байтов размера MTU-заголовков приведет к фрагментации IP-адреса и другим издержкам, которые снизят производительность.

Вадим Сураев
источник
Это «воксельная» игра, так что да, ей нужно будет отправить много данных сцены.
KaareZ
@KaareZ Ну, в любом случае, вы, возможно, захотите отправлять их как отдельные независимые сообщения в этом случае, используя свои собственные механизмы повторной передачи. Minecraft был запущен по TCP и практически не воспроизводился в интернете; переход на UDP был счастливым событием для большинства людей. Основная идея заключается в том, что когда вы отправляете 20 фрагментов данных вокселей, а первый «теряется», он не должен блокировать показ остальных 19 фрагментов, как только вы получите данные; когда вы обнаружите, что первый отсутствует, вы ретранслируете. В TCP все эти 19, по крайней мере, останавливаются и в худшем случае ретранслируются.
Луаан
2
@Luaan Minecraft не переключился на UDP для реального игрового процесса. Даже самые последние версии все еще используют TCP. Не повод для радости ... :( Единственная часть Minecraft, которая использует UDP, это список серверов, чтобы пинговать отдельные серверы и определять, находятся ли они в сети.
camerondm9
1

Ни UDP, ни TCP (ни какой-либо другой вариант) не превосходят по достоинству , даже с точки зрения скорости / задержки. Ваш выбор должен быть сделан в зависимости от требований вашего приложения. Чтобы сделать это, вы должны сравнить функции, которые предлагает каждый протокол, понимая, что больше функций предполагает больше накладных расходов. Таким образом, если цель состоит в том, чтобы минимизировать задержки или максимизировать скорость, вам следует выбрать протокол с как можно меньшим количеством функций, но при этом сохранить основные функции, необходимые для удовлетворения ваших требований.

Сравнение протоколов

Вообще говоря, UDP (User Datagram Protocol) предлагает наименьшее количество функций. Это упрощает то, что вы отправляете данные без какого-либо получения / подтверждения.

С другой стороны, TCP (протокол управления передачей) предлагает большинство функций, необходимых для надежного соединения. TCP-соединение отправляет дубликаты или более пакетов и маркирует их информацией для заказа. После получения в пункте назначения ACK (подтверждение) должен быть отправлен обратно вместе с информацией о том, какие пакеты были потеряны, чтобы исходный отправитель мог повторно отправить эти потерянные пакеты. Если я правильно помню, даже пакеты ACK могут нуждаться в подтверждении для надлежащей надежности.


Пример: Skype Конференц-связь

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

Однако во время конференц-связи люди могут отправлять мгновенные сообщения (мгновенные сообщения) или отправлять файлы. В этих случаях надежность является необходимым требованием для обеспечения того, чтобы файлы и сообщения не были повреждены или потеряны. Для мгновенных сообщений вам может не понадобиться подключенное состояние, которое обеспечивает TCP. Промежуточный протокол, такой как RUDP (надежный UDP), может быть достаточным. Однако для файлов может потребоваться наличие подключенного состояния, которое обеспечивает TCP.


Варианты реализации

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

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

Николас Миллер
источник
1

Я заметил много комментариев, где люди считают, что TCP-пакеты больше, чем UDP-пакеты. Не доверяй мне, читай документацию. Протокол следующий: несколько байтов для заголовка Ethernet (тип сообщения 2 байта, MAC-адрес 48 бит, 6 байтов) (для Wifi заголовок может отличаться) 20 байтов для IP 20 байтов для TCP или UDP x байтов для данных x ранжирование от 0 до примерно 1500 (см. MTU) Наконец, контрольная сумма, чтобы убедиться, что в этом пакете Ethernet не произошло искажения.

TCP позволяет отправлять большие «потоковые» пакеты размером около 64K. Этот «большой» блок фактически прерывается на множество меньших пакетов Ethernet.

Joust6809
источник
Вы пытаетесь предположить, что заголовки UDP и TCP имеют одинаковый размер?
Кэмерон