Я знаю, что UDP обычно рекомендуется для многопользовательских игр в реальном времени с высоким использованием данных.
Большинству статей посвящено несколько лет, и, поскольку ~ 80% всех данных, передаваемых в Интернете, - это TCP, для TCP должна быть проведена большая оптимизация.
Это заставляет меня задуматься: по-прежнему ли UDP превосходит скорость и задержку? Могли ли недавние оптимизации TCP сделать TCP работать лучше, чем UDP?
c++
networking
udp
realtime
KaareZ
источник
источник
Ответы:
Нет, UDP по-прежнему превосходит по задержке
производительностии всегда будет быстрее из-за философии двух протоколов - при условии, что ваши коммуникационные данные были разработаны с учетом UDP или любых других коммуникаций с потерями.TCP создает абстракцию, в которой поступают все сетевые пакеты, и они приходят в точном порядке, в котором они были отправлены. Чтобы реализовать такую абстракцию на канале с потерями, он должен реализовать повторные передачи и тайм-ауты, которые занимают время. Если вы отправите 2 обновления по TCP, и пакет первого обновления будет потерян, второе обновление не будет отображаться до тех пор, пока:
Не имеет значения, насколько быстро это делается в 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.
источник
Мы согласны с тем, что TCP и UDP являются протоколами, основанными на IP , не так ли? IP определяет, как сообщения доставляются через Интернет, но ничего не касается структуры, формата сообщений. Здесь идут протоколы TCP и UDP. Они используют свойства IP, но позволяют программисту сосредоточиться на обмене сообщениями, не беспокоясь о нижних уровнях сетевого взаимодействия. И это здорово, потому что иметь дело с аналоговыми сигналами в проводах напрямую было бы болезненно.
TCP предоставляет набор функций для отправки и получения сообщений. Он делит наши данные на небольшие пакеты для себя и отправляет их по сети. Все, что нас просят, это порт, используемый для сетевого сокета, и реальное сообщение, которое мы хотим отправить. Кроме того, это надежно, то есть, если некоторые пакеты будут потеряны в сети, в которой они обнаружены, то отправляются снова, заботясь об отправке их в том же порядке, в котором они должны были прибыть.
С другой стороны, UDP - это протокол, ориентированный на управление пользователями. При использовании UDP для отправки наших дейтаграмм , мы не можем быть уверены, что датаграмма когда-нибудь прибудет в пункт назначения или нет (и здесь мы подразумеваем математическую уверенность: когда мы отправляем пакет, он, вероятно, прибудет, но мы не можем быть уверены, что 100%). Кроме того, когда пакет потерян, он не будет ни обнаружен, ни отправлен снова.
На этом этапе TCP будет выглядеть как идеальное решение всех наших проблем. Это надежно, быстро, это решает задержку соединения для нас, отслеживая, какие пакеты поступили и какие пакеты нам еще нужно отправить.
НО , смотрите дальше. Единственное преимущество, которое дает нам UDP, - это его скорость, и это единственное, чего мы действительно хотим. Пакет UDP просто создается, проверяется и отправляется без каких-либо определенных элементов управления, потому что именно так работает протокол UDP. Пакет TCP должен быть обработан, помечен, проверен на наличие сумм, и когда он прибывает, ACK отправляется обратно, чтобы сообщить отправителю «пакет x здесь, продолжайте идти» , и когда этот сигнал не отправляется, это означает, что такой пакет x должен быть отправлен очередной раз.
Да, но не только. UDP в значительной степени предпочтительнее, чем TCP, главным образом потому, что его высокая скорость является идеальной для обработки больших объемов данных и управления ими. Это происходит, когда, предполагая, что такая видеоигра работает на детерминированном шаге (то, что происходит на сервере, одинаково реплицируется на любом клиенте независимо от задержки в сети), пакет обновления теряется и никогда не достигает своего места назначения. TCP будет повторно отправлять такой пакет, и следующие пакеты будут отброшены, поскольку поступают не по порядку, а затем повторно отправляются после потерянного. UDP гораздо более терпим в этом сценарии: он не будет заботиться об этом пакете, потому что приходят новые обновления. Потерянное обновление не отображается, вместо этого физика игры интерполируется по используемому методу интеграции и получению последнего обновления.
TCP вызывает дрожание, когда задержка достаточно высока, UDP не:
Ну да, так и будет долго . Вы можете узнать больше о TCP против UDP здесь .
источник
TCP <- протокол управления передачей. Это сделано для контроля передачи.
TCP был создан, чтобы быть хорошим и дипломатичным гражданином сети. Он направлен на то, чтобы сделать работу с сетью хорошим опытом для всех, и охотно снижает ее пропускную способность для достижения этой цели. Это приспосабливается к окружающей среде, добавляя задержку . Причины, например:
Дополнительно
Несмотря на это, TCP обеспечивает самый высокий показатель для (общих передаваемых данных) / (общего потребляемого времени). Просто это не происходит именно тогда, когда вы хотите, чтобы это произошло.
UDP не делает ничего из этого. Он стреляет по вашей воле, просто никто не может ожидать, что он будет поражать каждый раз - если цель должна объявить, что «вы не стреляли в течение долгого времени, почему?». Можно по-прежнему создавать собственные настраиваемые пакеты ACK, помещать несколько записей в один пакет и т. Д. А также важно контролировать обход NAT. UDP, безусловно, подходит для игр с низкой задержкой.
источник
Вы можете сравнить первую диаграмму 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 довольно неинтересна, потому что компьютер может просто сделать новый запрос, а не пытаться сообщить удаленной системе о наличии невыполненного предварительного запроса.
источник
Подумайте, что происходит на мгновение. Чтобы упростить сценарии, у вас есть два варианта при попытке отправить изменение состояния (например, ваш игрок только что сменил направление, или выстрелил из пистолета, или какой-то другой игрок просто сбросил бомбу):
Предполагая, что не было никакого обновления, необходимого прямо перед ним, время, когда это единственное обновление прибывает в 1 против 2, не будет очень отличаться. Это одна поездка от сервера к клиенту. Но, скажем, вместо того, чтобы просто взорвать бомбу, вы пытаетесь постоянно передавать действия кого-то, бегущего через лабиринт; ткачество, уклонение, стрельба и т. д. В случае UDP каждое действие будет отправлено в дейтаграмме, как только это произойдет. В случае TCP каждое действие будет отправлено в пакете, только если серверу разрешено отправлять. Что говорит, что разрешено отправлять? Наличие места в окне TCP (при условии, что задержка подтверждения активна), так что сообщение может быть передано по проводам. Если нет, он должен дождаться подтверждения получения от клиента перед отправкой.
Как долго это слишком долго? Когда разработка многопользовательских шутеров от первого лица пошла на спад, в конце 90-х и начале 2000-х годов соединения с малой задержкой не были обычным явлением. Модемный модем будет иметь типичную одностороннюю задержку 180 мс. Ожидать ack перед отправкой другого обновления, фактически удваивая это время до 360 мс, было больно; Даже начинающие пользователи могут почувствовать разницу. Когда широкополосные соединения завоевали популярность, они значительно снизили задержку, но она все еще сохранялась, когда пропускная способность была в дефиците (довольно часто в некоторых областях). Таким образом, предпочтение минимальной возможной задержки сохранялось.
Современные домашние соединения и соединения изменили это до такой степени, что региональная задержка, даже в перегруженное время суток, находится в диапазоне 15 мс или ниже. Выбор TCP вместо UDP был бы невидим в большинстве случаев, так как задержка «достаточно низкая». Тем не менее, все еще существует тенденция приоритета UDP по сравнению с 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 обязательно будет включать потерянные пакеты (именно так работает контроль перегрузки).
источник
В 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 также хорош для данных, которые желательны, но не обязательны. Прямое исправление ошибок - пример этого, много ненужных, но желательных пакетов.
источник
Еще один вопрос: означает ли «интенсивный обмен данными», что вы будете часто загружать сцены?
Если да, вам может понадобиться интенсивно отправлять большие фрагменты данных (> 1 Кб), в которых TCP может быть гораздо более эффективным, поскольку, особенно на стороне сервера, сетевые адаптеры будут обеспечивать различные нагрузки, которые имеют одинаковую серию циклов. Приложение пользовательского пространства может выдавать большие записи по протоколу TCP, тогда как в UDP попытка отправки более байтов размера MTU-заголовков приведет к фрагментации IP-адреса и другим издержкам, которые снизят производительность.
источник
Ни UDP, ни TCP (ни какой-либо другой вариант) не превосходят по достоинству , даже с точки зрения скорости / задержки. Ваш выбор должен быть сделан в зависимости от требований вашего приложения. Чтобы сделать это, вы должны сравнить функции, которые предлагает каждый протокол, понимая, что больше функций предполагает больше накладных расходов. Таким образом, если цель состоит в том, чтобы минимизировать задержки или максимизировать скорость, вам следует выбрать протокол с как можно меньшим количеством функций, но при этом сохранить основные функции, необходимые для удовлетворения ваших требований.
Сравнение протоколов
Вообще говоря, UDP (User Datagram Protocol) предлагает наименьшее количество функций. Это упрощает то, что вы отправляете данные без какого-либо получения / подтверждения.
С другой стороны, TCP (протокол управления передачей) предлагает большинство функций, необходимых для надежного соединения. TCP-соединение отправляет дубликаты или более пакетов и маркирует их информацией для заказа. После получения в пункте назначения ACK (подтверждение) должен быть отправлен обратно вместе с информацией о том, какие пакеты были потеряны, чтобы исходный отправитель мог повторно отправить эти потерянные пакеты. Если я правильно помню, даже пакеты ACK могут нуждаться в подтверждении для надлежащей надежности.
Пример: Skype Конференц-связь
Для конференц-связи Skype не важно, чтобы все видео и аудио данные отправлялись / принимались надежным способом. В настоящее время UDP отлично справляется с задачей минимизации потерь пакетов. Важно знать, что в UDP нет абсолютно никакой гарантии, была ли передача успешной. Для аудио- и видеоданных во время конференц-связи UDP является правильным выбором, поскольку мы больше заботимся о получении данных в режиме реального времени (то есть самых последних). Если несколько пакетов потеряны здесь и там, это не прервет связь драматическим способом.
Однако во время конференц-связи люди могут отправлять мгновенные сообщения (мгновенные сообщения) или отправлять файлы. В этих случаях надежность является необходимым требованием для обеспечения того, чтобы файлы и сообщения не были повреждены или потеряны. Для мгновенных сообщений вам может не понадобиться подключенное состояние, которое обеспечивает TCP. Промежуточный протокол, такой как RUDP (надежный UDP), может быть достаточным. Однако для файлов может потребоваться наличие подключенного состояния, которое обеспечивает TCP.
Варианты реализации
Если у вас сложное приложение или вам необходимо оптимизировать ваше общение, то начинать с UDP-соединения выгодно. После этого вы можете добавить все функции, которые вам нужны, сверху. Это даст вам максимальный контроль над сетевым взаимодействием.
Если у вас есть простое приложение, в котором оптимизация не требуется, рассмотрите возможность использования одного из стандартных (UDP или TCP) для удовлетворения ваших потребностей. Это позволит вам перейти к более важным вопросам.
источник
Я заметил много комментариев, где люди считают, что TCP-пакеты больше, чем UDP-пакеты. Не доверяй мне, читай документацию. Протокол следующий: несколько байтов для заголовка Ethernet (тип сообщения 2 байта, MAC-адрес 48 бит, 6 байтов) (для Wifi заголовок может отличаться) 20 байтов для IP 20 байтов для TCP или UDP x байтов для данных x ранжирование от 0 до примерно 1500 (см. MTU) Наконец, контрольная сумма, чтобы убедиться, что в этом пакете Ethernet не произошло искажения.
TCP позволяет отправлять большие «потоковые» пакеты размером около 64K. Этот «большой» блок фактически прерывается на множество меньших пакетов Ethernet.
источник