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

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

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

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/ для обсуждение). Если этот подход будет реализован (что может быть сделано поверх совершенно ненадежных пакетов) - он обеспечит ОЧЕНЬ значительное улучшение по сравнению с TCP (он устраняет блокировку HOL, поэтому мы говорим о задержках порядка тиков сети - и это может не более 1/120сек ~=8 мс - из-за задержек вокруг RTT, и они составляют не менее 100 мс для одного потерянного пакета).

Дополнительный комментарий:

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

Проблема с неупорядоченными пакетами.

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

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

Эрик-Юль @ Unity Technologies

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

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

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

Вот почему я хотел бы ответить на ваш вопрос со ссылкой на статью Reliable UDP (RUDP): The Next Big Streaming Protocol?:

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

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

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

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


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

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

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

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

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

Я уже упоминал проблемы с TCP.

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

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

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

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

Другие вопросы по тегам