Почему разработчики игр избегают TCP и делают UDP надежным на уровне приложений?

Многие разработчики игр делают UDP надежным на уровне приложения. Разве не для этого создан TCP? Я сделал API, который обеспечивает связь клиент-сервер с использованием пакетов UDP и TCP. Стоит ли добавлять в список надежный UDP? И почему? Есть ли проблема, если я использую TCP?

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


person None    schedule 05.09.2016    source источник
comment
Я просто хочу знать, имеет ли RUDP какие-либо преимущества по сравнению с TCP, чтобы я мог выбирать, добавлять ли поддержку RUDP или нет.   -  person None    schedule 05.09.2016
comment
Ооооо, я совершенно неправильно понял суть твоего вопроса. Я не видел сделать UDP надежным на уровне приложений. Я думал, что это вопрос TCP против UDP, мои извинения, друг   -  person MickyD    schedule 05.09.2016
comment
Есть ли у вас источник утверждения, что многие разработчики игр делают UDP надежным на уровне приложений? Мне это кажется довольно глупым по причинам, о которых вы говорите.   -  person David Schwartz    schedule 05.09.2016
comment
Спросите разработчиков игр на #gamedev (Freenode), использовать ли TCP или RUDP. Они всегда будут выбирать RUDP. Однако некоторые разработчики игр на # reddit-gamedev видят, что TCP не такой медленный и может использоваться в играх для обеспечения надежности некоторых пакетов. Я просто не знаю, с каким мнением я бы согласился, поэтому попросил дать более точные ответы. Посмотрите на gafferongames.com/networking-for-game-programmers / Я до сих пор не знаю, какой вариант выбрать.   -  person None    schedule 05.09.2016


Ответы (4)


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

Больше всего задержек страдает блокировка заголовка (также известная как блокировка HOL): если один пакет потерян, все последующие пакеты в том же потоке, даже если они достигают другой стороны связи, не могут достигнуть уровня приложения (ой!), пока потерянный пакет не будет повторно передан (а это займет около 2 * RTT, что даже для сервера на каждом континенте составляет около 100 мс (= "в шутере вас уже убили )).

Длинный ответ:

Это сложный предмет, и нам нужно различать несколько различных сценариев:

  1. нам ДЕЙСТВИТЕЛЬНО нужен надежный упорядоченный поток сообщений (или байтов). В этом случае преимущества RUDP по сравнению с TCP, хотя и присутствуют, очень минимальны (мы можем немного поиграть с уменьшением времени повторной передачи - и устранить экспоненциальную задержку, но это почти все). В частности, блокировка начала линии по-прежнему неизбежна при ЛЮБОМ виде надежных упорядоченных потоков (будь то TCP, RUDP или что-то еще).

  2. нам НЕОБХОДИМО надежная, но потенциально неупорядоченная доставка сообщений. Это МОЖЕТ позволить избежать блокировки HOL, но требует довольно сложной обработки на уровне приложения.

  3. нам вообще НЕ нужна надежность (= «выстрелил и забыл»). Один из ярких примеров такой информации - это когда нам нужно показать попадание пули - если мы не показали его сразу, нет необходимости показывать его через полсекунды, поэтому, если пакет не прошел - ну, лучше просто игнорировать это и не тратить ресурсы на повторную отправку пакета.

  4. нам НЕОБХОДИМО синхронизированное в конечном итоге состояние (но мы НЕ заботимся о прохождении всех промежуточных состояний); это чрезвычайно распространенный сценарий для моделирования. Это возможно реализовать через UDP (и без штрафных санкций за блокировку HOL). Однако включение сжатия через ненадежные соединения не является тривиальным делом, и сжатие ОБЯЗАТЕЛЬНО для большинства игр. К счастью, такое сжатие выполнимо (см. http://gafferongames.com/networked-physics/snapshot-compression/ и / или http://ithare.com/udp-from-mog-perspective/#low-latency-compression для обсуждения). Если этот подход будет реализован (который может быть реализован поверх совершенно ненадежных пакетов) - он обеспечит ОЧЕНЬ значительное улучшение по сравнению с TCP (он устраняет блокировку HOL, поэтому мы говорим о задержках порядка сетевых тиков - и это может быть всего лишь 1/120 с ~ = 8 мс - по сравнению с задержками вокруг RTT, и это не менее 100 мс для одного потерянного пакета).

Боковой комментарий:

Фактически, МОЖНО имитировать UDP через TCP (устраняя задержки TCP) - см. http://ithare.com/almost-zero-additional-latency-udp-over-tcp/. Обратите внимание, что для его использования все вышеперечисленное нужно делать вручную. По-прежнему не существует волшебной палочки, позволяющей избежать блокировки HOL для надежно упорядоченного потока; вместо этого - этот метод позволяет заставить несколько TCP-соединений вести себя "почти так, как будто" это ненадежный, но неблокирующий UDP.

person No-Bugs Hare    schedule 26.05.2017
comment
Эти ссылки фантастические; Ты мой герой! - person None; 26.05.2017

Проблема заключается в неупорядоченных пакетах.

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

RUDP меняет все это и просто предоставляет самый последний пакет, как заявляет Эрик из Unity:

Эрик-Джул @ Unity Technologies

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

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

person MickyD    schedule 05.09.2016
comment
@Am_I_Helpful Я, и ты победил меня на 2 минуты хе-хе. Желаю вам удачи :) - person MickyD; 05.09.2016
comment
На практике проблема действительно в том, что TCP хочет перехватить все полученные пакеты, пока они не будут получены в том порядке, в котором их ожидает приложение (*). Однако в реальной жизни в 99% случаев это происходит не из-за неупорядоченных пакетов (что бывает редко), а из-за потерянного пакета (что очень часто). Этот отсутствующий пакет вместе с (*) приводит к так называемой блокировке заголовка (HOL Blocking), которая вызывает МНОГО проблем для динамичных игр. - person No-Bugs Hare; 26.10.2017

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

Поэтому я хотел бы ответить на ваш вопрос со ссылкой на статью _ 1_:

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

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

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

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


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

Если вы можете терпеть скорость обработки данных на обоих концах, это нормально.

Но в играх это не нормально. Вы должны передавать кадры видео (и аудио и т. Д.) Много раз в секунду, и это тоже для многих игроков (в многопользовательской игре). Все это требует гораздо большей скорости и более быстрой обработки данных; вместо использования сравнительно более медленного TCP. Даже если некоторые пакеты отбрасываются на полпути, это нормально для приложения, так как мозг тоже перейдет к следующему, вместо того, чтобы думать об этих дрожаниях.

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

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

Я уже упоминал о проблемах с ПТС.

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

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

person Am_I_Helpful    schedule 05.09.2016
comment
Ты сказал это лучше :) - person MickyD; 05.09.2016
comment
@MickyD - Спасибо, :) - person Am_I_Helpful; 05.09.2016
comment
Наш мозг может представить нам пропущенные фрагменты видео - ну да; однако идея пропустить пропущенные пакеты молча предполагает, что пакет влияет только на один кадр или около того. Это предположение оказывается совершенно неверным для большинства современных методов сжатия видео; в реальном мире Интернета очень редко случается, что каждый кадр является ключевым кадром, и обычно ключевые кадры разделены на несколько секунд; и пакет, потерянный сразу после ключевого кадра, приведет к потере видео до следующего ключевого кадра, что обычно неприемлемо. Следовательно, современная потоковая передача видео в основном основана на TCP. - person No-Bugs Hare; 23.08.2020
comment
отбрасывает что-либо из пересылаемого пакета вне очереди, отправляет сообщение вернуться туда, где пошло не так, и снова начинает передачу. - это было исправлено в RFC2018 в 1996 году (!) и является частью всех основных реализаций стека TCP в течение как минимум 15 лет. - person No-Bugs Hare; 17.12.2020
comment
продолжать общий поток видео - не будет работать ни с одним серьезным кодеком (точнее - с любым кодеком, у которого не каждый кадр является ключевым). - person No-Bugs Hare; 17.12.2020

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

Ссылка: http://www.diffen.com/difference/TCP_vs_UDP

person Legoboy0215    schedule 05.09.2016
comment
Ооо не знал этого. - person Legoboy0215; 05.09.2016
comment
Вы не ошиблись, но почему они делают UDP надежным? Разве они не должны просто использовать TCP? Есть например разница в скорости? Или это просто изобретение велосипеда? - person None; 05.09.2016
comment
Думаю, мы оба совершили одну и ту же ошибку, лего. Обратите внимание, OP хочет знать, почему разработчики игр по существу используют ненадежный протокол, такой как UDP, и делают его надежным на уровне приложения - person MickyD; 05.09.2016