Изучаю бэкенд игровую разработку и делаю свой тестовый проект. В прод он не пойдет, делаю для себя, для обучения, простой сервер для MMORPG.
Есть несколько вопросов про сетевую часть:
1. Правильно я понимаю, что если использовать UDP, то в каждый пакет надо добавлять данные для определения от кого этот пакет, т.е. своеобразную сессию?
2. Как обычно используется UDP в игровой разработке?
3. Все ли используют RUDP или для каких-то случаев подойдет обычный UDP?
Талян, потому что пакеты UDP быстрее проскакивают через маршрутизаторы, не встречая на своем пути интересные алгоритмы управления потоком, которые применяются к пакетам TCP
Талян, дополню себя тем, что идеальный профиль нагрузки для TCP, это когда в сокет нечасто записывают сразу огромный блок, после чего ОС начинает его отсылать пакетами размером с MSS c максимальной установившейся скоростью
В то же время, профиль, формируемый игрой - это отправка 5-15 мелких блоков каждую секунду, что сразу сталкивается с разными алгоритмами, препятствующими появлению флуда - вроде алгоритма Нейгла.
потому что пакеты UDP быстрее проскакивают через маршрутизаторы, не встречая на своем пути интересные алгоритмы управления потоком, которые применяются к пакетам TCP
Это не так. Для сетей маршрутизации пакет все равно представлен IP датаграммой, будь это TCP- или UDP-пакет.
Правила роутинга по протоколам транспортного уровня имеются, но не являются страшными.
TCP не используют в связи с тем, что чаще всего не знают как по каналу передавать свои данные. Зачастую я в сетевом коде проектов наблюдаю полнейший бедлам без структуры и какого-то намека на здравый смысл. Люди в датаграмму UDP пишут как будто в файл со своей строго определенной тематикой и отсылают десятки и сотни таких датаграмм за один такт симуляции.
Отдельные люди, кому посчастливилось читать Гленна Фидлера, пробуют реализовать свой сеансовый уровень поверх UDP тоже не изобилуя структурностью данных в пакете.
А по TCP обычно вижу передачу json-ов и xml-ек а-ля SOAP и такое прочее. За голову хвататься в пору с таких зрелищ. :)
Талян
TCP можно использовать и его используют. Просто считается, не без эффекта весомости мнения Гленна, что TCP увеличивает латентность передачи данных. Слухи молвят что TCP безусловно буферизирует исходящий трафик до заполнения всего кадра отправки. И что это может привести к латентности в сотни миллисекунд, что недопустимо для игр.
Это тоже неправда, задержку от буферизации TCP можно нивелировать техническими приемами и настройками протокола.
При этом у UDP есть другая, куда более серьезная, проблема, связанная с MTU, фрагментацией и алгоритмами этой самой фрагментации в роутерах разных производителей.
MTU (Maximum Transmission Unit) определяет максимальный размер пакета, который не подвергнется фрагментации при передаче по определенному маршруту.
Алгоритмы фрагментации бывают разные, но основных - два: Traffic Shaping и Traffic Control.
Шейпинг просто режет датаграмму "под орбу". Все что больше MTU отсекается, остальное отправляется дальше по маршруту. Множество дешевых домашних роутеров занимаются именно этим при маршрутизации.
Контроль организует фрагментацию датаграммы до размера MTU и отправляет уже как цепочку фрагментированных датаграмм.
Оба этих алгоритма резко повышают шансы большой датаграммы стать потерянной. И если при контроле датаграмма может быть только частично потеряна, то в результате шейпинга датаграмма вообще всегда считается потерянной, даже если доставлена. Такие датаграммы на обработку могут поступить только если были отправлены с соответствующими флагами.
И вот еще вишенка на этом торте: по разным маршрутам могут встречаться разные устройства с разными алгоритмами фрагментации. Тут пакет законтроллили, а там - уже зашейпили и всё.
Многие протоколы сегодня из-за этого боятся слать датаграммы больше 500Б. При этом, таких датаграмм отсылается в избытке, что создает значительную сервисную нагрузку на сетевой канал. Ведь каждая датаграмма будет нести в себе один и тот же IP заголовок (28/48Б в зависимости от версии протокола IP), а это до 10% трафика при датаграммах по 500Б.
В этом плане TCP значительно выгоднее за счет только того, что берет на себя весь этот сервис с пакетами.
Профиль современной игры (на дистанции уже 12 лет) требует канал от 512КБит/сек до 2.5МБит/сек, что складывается из 30, 60 или 96 операций приема-передачи трафика около 1-2КБ за одну операцию приема-передачи.
Евгений Шатунов, Проблема очень простая - как поступает средний программист. Он берет и посылает в TCP и в UDP сегменты одинакового размера, после чего смотрит время отклика - и наблюдает, что с ростом числа отправленных сегментов в секунду, TCP начинает отставать, причем при большом расстоянии между хостами в плане географии, остает драматически (RTT умножается на три, а то и на пять)
После этого остается выбор - взять UDP, который очевидно, работает здесь и сейчас, или заниматься мифическими действиями:
задержку от буферизации TCP можно нивелировать техническими приемами и настройками протокола
которые сегодня может быть сработают, завтра - не сработают. Или у разработчика работает - а у клиента - нет, потому что у него провайдер, который использует шейпер трафика, который в свою очередь, осуществаляет интересные манипуляции с TCP Window, что и приводит к буферизации.
Разумеется, если у вас есть литература или статьи, которые объективно показывают, как настроить TCP, чтобы RTT не умножалось в разы при изменении размера посылаемого пакета, я с радостью ознакомлюсь.
Армянское Радио, эти мифические действия работают всегда и у всех. Говорю об этом как разработчик уже трех ММО проектов с сетью на базе TCP протокола (кастомы RO, Minecraft и проект Skylore) и разработчик сетевого уровня таких проектов, как Quake Champions и WWZ, сеть в которых строится поверх UDP.
Мы решали разные проблемы трафика для iOs, Android, PS4, XBox, ПК и Switch. И всегда добивались нужного результата. И я сразу сказал что с UDP проблем фрагментации значительно больше.
Статей в открытом доступе нет, есть только за деньги и за участие в игровой индустрии. Но это не беда, ведь есть документация сокетов Беркли. Там все хорошо описано, при ее изучении можно до всего дойти самостоятельно.
Армянское Радио, для меня, на самом деле, оба транспортных протокола выглядят равнозначными при соблюдении условий их применения.
UDP действительно позволяет быстрее доставить данные. Более того, зачастую я могу даже отключить проверку целостности датаграммы чтобы повысить шанс ее доставки ценой порчи ее данных. Доставка хоть части данных бывает выгоднее ее потери из-за повреждений.
TCP же позволяет рекордно сократить расходы на разработку протокола за счет своих свойств тогда, когда важна не только гарантированная доставка, но и доставка со строгим соблюдением очередности данных.
Исходя из свойств игры, требований к сети и условий разработки можно сделать выбор между одним или другим. И не всегда этот выбор бывает окончательным. При необходимости TCP можно позже заменить более быстрой схемой гарантированной доставки на базе UDP от Гленна Фидлера.