Comments 55
UDP-пакеты не шифруются

В UDP отсутствует аутентификация

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


Думаю дело как раз в гарантии целостности данных.
Причем UDP можно защитить DTLS (Datagram Transport Layer Security): https://tools.ietf.org/html/rfc4347
Вообще непонятен момент как он перешел от фазы «браузеры не умеют и не должны уметь UDP» к фазе «Вот вам протокол, тут есть UDP и мы можем на нем писать игры».
Это некий плагин к браузеру, или что?
П.С.: На гитхабе тоже об этом умалчивается. Везде формулировка типа «netcode.io это протокол».
Так он вроде нигде не говорит, что это работает в браузерах. «Это протокол».

Непонятно что ему мешало сделать прозрачную прослойку поверх WebRTC.

IMHO, не выстрелит, т.к. нельзя легко пощупать.
Т.е. сначала создаём себе трудности — пытаемся писать игры в браузере — а потом их героически преодолеваем.
Может, не стоит забивать гвозди пассатижами?
Ставить клиент — это автоматически отсечь половину пользователей.
Да я понимаю, что юзверям надо «всё, сразу, бесплатно и без регистрации». Более того, сам пользуюсь веб-клиентами к некоторым IM-сервисам. Но всё равно какое-то чувство неправильности происходящего остаётся.
Как у Лема в его истории про всё более и более навороченные стиральные машины, которые в конце своей «эволюции» уже и стирать-то не могли (и не хотели).
Итак, совершенно ясно, что JavaScript ни в коем случае не должен создавать UDP-пакеты в браузере

честно говоря не убедили, шифрование и аутентификация не всегда нужны, DDoS можно ограничить соединение лишь со своими доменами, прощупывать можно и с TCP.
Я бы даже сказал что совсем не убедили.

В том же Adobe Flash есть некий DatagramSocket, который, согласно мануалу, — умеет:
>>The DatagramSocket class enables code to send and receive Universal Datagram Protocol (UDP) packets.

Флеш конечно та еще дырища, однако историй DDoS с помощью этого функционала я припомнить не могу.

Удивительно почему автор, считающий себя таким большим специалистом, — не упомянул про это.
Проблема с TCP надуманна и преувеличена.
в случае плохого соединения нормально поиграть не получится независимо от протокола
а в случае хорошего соединения
1) 60-100мс пинг до сервера
2) ~200мс лаг человеческого восприятия
3) <1мс какая-то там разница между TCP и UDP

скажите мне что я не учел?
да кстати что это за дурацкий принцип, который они называют «блокировкой начала очереди», мы же ведь не собираемся отправлять пакеты в бесконечном цикле, забивая весь канал, а потом жаловаться что что-то пошло не так. или собираемся? и будем жаловаться на TCP?
Представим игру, в которой сервер раз в 20 секунд отправляет клиенту по TCP координаты игрока (интервал в 50 миллисекунд). Допустим, что средний пинг конкретного соединения между клиентом и сервером равен 100 миллисекундам, чего более чем достаточно для комфортной игры. Но вдруг один из пакетов дропнулся. В этом случае сервер подождет некоторое время SRTT(Smoothed Round Trip Time), которое равно примерно среднему пингу, т.е. 100 миллисекунд и потом отправит этот пакет повторно, который будет идти до клиента еще 50 миллисекунд.

При этом все остальные пакеты (в данном случае 150/50=3 штуки) были доставлены вовремя, но «протухли» в буфере клиента, поскольку перестали быть актуальными. Вот такая ситуация и называется блокировкой начала очереди.

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

А в случае передачи по UDP сервер ничего не передает повторно, но и клиент ничего не ждет. И в данной ситуации фриз будет всего 50 миллисекунд вместо 150.
во первых отправлять пакеты 20 раз в секунду неправильно. о чем я и говорил. отправлять пакеты надо по мере необходимости, когда есть новые данные.
во вторых TCP пакет на нормальном соединении просто так не дропнется. если у вас дропаются TCP пакеты, что-то сильно пошло не так, и никакое UDP уже не поможет
в третьих, TCP это транспортный протокол, который сам решает транспортные проблемы. если что-то там внутри него и дропается, он исправляет проблему, и делает это очень быстро. все что вы сможете заметить — небольшой скачек пинга.
1) В онлайн-игре каждый тик симуляции меняет игровую ситуацию. Как правило, частота передачи пакетов игрового состояния равняется частоте тиков симуляции. Так что новые данные есть всегда.

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

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

3) Все верно, TCP решает все транспортные проблемы. Но что значит «очень быстро»? Как я показал, TCP решает проблему как минимум за время пинга. Если этот пакет несет в себе часть картинги в браузере, то это не критично, но даже в этом случае это не очень быстро, а достаточно быстро. Если же это кадр тика симуляции, то увеличение срока его доставки минимум в полтора раза — это очень медленно.
1) Пишем свой небольшой тестовый клиент и сервер, сервер запускаем на VDS, пинг до которого примерно 100мс.
2) отправляем несколько тысяч tcp пакетов, замеряем средний пинг
3) отправляем несколько тысяч udp пакетов, замеряем средний пинг. потерянные пакеты выбрасываем
4) думаете разница будет хоть сколько-то значительна?))
Нам не нужно мерить пинг, нам нужно мерить время доставки пакетов — это разные вещи.

Тогда в случае плохого коннекта на TCP время доставки будет выше, чем на UDP.

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

Когда коннект не идеален, в обоих протоколах скорость доставки увеличится, но при TCP увеличится на большее значение.

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

когда говорят что UDP «быстрый» имеется ввиду уменьшение накладных расходов, что выгодно при передаче жирного трафика вроде потокового видео. Или в том случае если у вас реально нагруженный сервер, например игра вроде League of Legends.

на стороне игрока разница не будет заметна. Я лично на своей первой работе играл в лигу легенд через прокси сервер, прокинув http-туннель до дома, и не заметил ни малейшего дискомфорта.

если уж такая вакханалия как UDP over HTTP прекрасно работает, чего уж там говорить о разнице UDP vs TCP
Нет, время доставки пакета — это сколько пакет шел в реальности, а пинг в данном контексте — это средняя скорость с которой пакет идет туда-обратно. Другими словами пинг можно считать некоей константой конкретного коннекта, идеальным временем доставки. В условиях интернета время доставки пакетов не всегда будет идеальным, т.е. не всегда будет равно половине пинга.

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

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

Откройте любую сетевую игру, просниферьте трафик и вы увидите, что такие игры открывают всегда минимум по 2 коннекта — udp для передачи скоропортящихся данных (игровое состояние) и tcp для передачи остальных данных (чат и прочее). И никакие накладные расходы и нагруженность тут ни при чем. Единственная причина — устранение очереди блокировок.
Можно без снифера провести простой тест — заблокируйте на роутере или на компе в файрволе весь udp трафик и попробуйте запустить какую-нибудь сетевую игру, мобу или мморпг и увидите, что ни одна из них не запустится, поскольку они все используют udp. Вы думайте, разработчики игр настолько тупые, что всегда используют два протокола вместо одного, раз tcp так хорош?
Я не отрицаю проблему протухания пакетов на устройстве, я отрицаю практическую важность этой проблемы, поскольку условия при которых она становится важной, создают не менее критичные проблемы для UDP протокола.

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

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

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

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

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

В TCP вам ГАРАНТИРОВАННО придет и старое добро и новое, это и есть задержка, с которой справляются с помощью UDP.

Дело не только в пинге, пингом мы определяем частоту обновления игрового мира. Важно, что в игре есть два типа данных: моментальные — такие как позиции игроков, выстрелы, боеприпасы, и остальные данные — например, количество экспы, монет.

Для этого и создают два соединения.

Такой подход используют в динамичных играх. В остальных случая можно и не заморачиваться.

PS.: А то, что у вас пробросился хорошо UDP по HTTP ни о чем не говорит, кроме как о том, что вы близко к серверу и у вас отличный канал, а так же о том, что к вам UDP пакеты прилетают пачками, обернутыми в TCP.
Сомнительная статья. Что udp, что tcp были разработаны со своими целями. Лучше использовать их вместе (в вебе пока хватает tcp с головой). А насчет шифрования это самое последнее о чем бы я подумал (уж очень часто автор упоминал шифрование).
К тому же NodeJs нативно асинхронен (Non-blocking IO). Далее не буду объяснять что да как.
Нет, все-же объясните, как нативная асинхронность node.js может изменить фундаментальные принципы работы протокола tcp.
В вебе уже не хватает с головой tcp. Автор привел очень конкретный пример, где tcp не хватает. В чем сомнительность?
Можно попробовать другой вариант выхода из положения. WebSockets позволяет только TCP, но зато не ограничивает количество одновременных подключений. Так что ни что не мешает вместо одного коннекта создать несколько и слать пакеты последовательно в разные. Можно пойти дальше, и слать пакеты избыточно в несколько коннектов, но придется написать дополнительные обертки на клиенте и на сервере, чтобы нумеровать пакеты и не обрабатывать один и тот же пакет, пришедший по разным коннектам. Можно пойти еще дальше и написать систему мониторинга, которая будет отслеживать качество соединения и подстраивать стратегию взаимодействия под реалии: изменять количество коннектов, определять величину избыточности и т.п.

И такой подход, как мне кажется, более уместен, чем пытаться навязать изменения в стандарт.
Он избыточен для браузерок по типу agar.io, а чтото более серьезное будет клиентским
Спорное утверждение. Игры во всю стремятся в браузеры, их качество растет, их бюджет растет и эта тенденция в обозримом будущем вряд ли прекратится, потому что браузер — это очень доступная и распространенная платформа для игр. Не стоит считать браузерки второсортным продуктом, посмотрите, например, на hordes.io. Избыточен ли для этой игры хороший коннект? Это инди игрушка. Будет ли избыточен хороший коннект для подобной игры, выпущенной большим игроком с приличным бюджетом? Я думаю, в обоих случаях ответ — нет, но во втором он более очевиден.
Вы можете себе представить 2-3к игроков на осадена Руны в браузере? Для серьезных игр онли клиент. Для остальных сойдет и браузер
Ок, 2-3к игроков. Нагрузку на сервер мы в расчет не берем, потому что серверу все равно какие у него клиенты.

Значит вы имеете в виду, что браузер не сможет отобразить/рассчитать одновременно 2-3к игроков? Да, не сможет. И клиент не сможет. Ни разу не видел игры с таким огромным количеством участников в одном месте. Не видел потому, что игроделы уже давным-давно поняли, что собирать толпу народа в ограниченном пространстве совсем не круто по целому ряду причин (нагрузка на сервер, нагрузка на сеть, нагрузка на видеокарту/процессор клиента, нагрузка на глаза и мозг игрока), поэтому придуманы различные инстансы, рейды, батлграунды, фаззинг и прочее. Одним словом, размазывание игроков по миру и сбор их в удобные группы — это вопрос геймдизайна, правила что для десктопного приложения, что для браузера совершенно одинаковы.
Зайдите на любой офф-сервер Lineage2, который запущен меньше года назад. Там и не такие толпы на осады собираются. И да… это в одной относительно компактной зоне вокруг замка, а в целом в практически бесшовном мире (не берем в учет инсты и локации в которые кроме телепорта никак не попасть) может быть гораздо больше.
Мне почему-то кажется что браузер легко потянет графику линейки ))) Но, даже, допустим, что не потянет, но процент таких игр очень мал. Подавляющее большинство популярных игр толпы в одном месте не собирает. А общее количество игроков в игровом мире ни на что кроме сервера не влияет. Сколько бы не было всего на сервере игроков, клиент обрабатывает и отрисовывает лишь тех, которые находятся в его зоне видимости, а об остальных он ничего не знает и знать не должен.
А вы бы попробовали сначала, а потом говорили.

зы. да и на таком количестве игроков пробелма с блокирвокой пакетов в очереди чувствуется ой как хорошо
На нормальной машине графика там не тормозит, тем более на осадах все красивости вырубаются в настройках. Я как раз о сети. В браузере не сделаешь такую работу с сетью как позволяет сделать клиент. Браузерка не вытянет передачи инфы о таком количестве игроков без тормозов со стороны сети.
Только UDP спасет отца русской демократии)
Ну что вы говорите, там в настройках можно установить предел количества отображаемых персонажей, и все тормоза на осаде тут-же прекращаются. Хотя все пакеты клиент конечно-же получает.
с точки зрения графики, там тормоза квадратично нарастают, так что клиент Lineage до сих пор нагибает даже современные компы (особенно с учетом того что видеокарта почти не задействуется, и работает все через 1 поток на CPU)
еще раз, я о работе с сетью. Клиент работает через udp. При использовании tcp играть было бы вообще невозможно
Не буду спорить, возможно чтото изменилось. В универе открывали эти порты и для udp
они используют старую глубоко-модифицированную версию Unreal Engine, с точки зрения движка там за почти уже 15 лет ничего значимого не поменялось
Вот это жесть полная будет. Столько накладных расходов и столько усложнения кода… а самое главное — обмануть физику все равно не удастся.
Вы считаете, что сеть либо хорошо работает, либо совсем не работает. Но это не правильная точка зрения — на самом деле реальное сетевое взаимодействие за пределами локальной сети практически всегда имеет те или иные проблемы, начиная от незначительных, которые вообще не заметны и заканчивая серьезными сетевыми проблемами. Но даже в случае серьезных проблем сеть не обязательно ложиться, она работает, просто не устойчиво — эта особенность была изначально заложена и, более того, была основным критерием при создании стека tcp/ip. И да, в случае серьезных проблем в данной задаче вряд ли получится избавиться от диких лагов, но мы тут ведем речь в основном про малые и средние проблемы, с которыми можно жить и которые можно побеждать.
Вовсе нет. Я считаю лишь то, что транспортные протоколы TCP и UDP реализованны оптимальным образом. а разница между ними именно для пользователя приложения — минимальная. Чем стоит озаботиться среднему разработчику — так это лаг-коменсацией. А вот если сделать то что вы предложили, поднять кучу коннектов, дублировать пакеты и все такое, станет только хуже.
Так разве кто-то утверждает, что TCP или UDP плохие протоколы? Они хорошие, если их использовать в надлежащих случаях. Проблема в том, что UDP нельзя использовать в браузере, хотя подходящие для него случаи есть.

Лаг-компенсация — это очень хорошо и приличные игры без нее не обходятся. Но не нужно смешивать 2 задачи в одну. Одна задача — уменьшить количество лагов. Вторая задача — сгладить последствия лагов. Эти две задачи не взаимозаменяемые, они взаимодополняющие.

Я предложил в первую очередь разделить трафик по нескольким коннектам, чтобы уменьшить (убрать) очередь блокировок. Дублирование — это вторично и опционально.
Кто мешает DDoS-ить левые ip-ники «запросами на подключение» по UDP? Как браузер (не javascript, а именно браузер) поймёт, что к данному ip-нику больше уже не надо слать эти пакеты?

Тут, imho, есть отличное место для использования обратного DNS.
Идея примерно такая — ПЕРЕД тем, как слать UDP на IP a.b.c.d, от имени сайта www.example.com браузер должен сделать запрос на, например, TXT поле d.c.b.a.in-addr.arpa, и если там таки www.example.com (или какой более умный синтаксис разбора — см. SPV, кажется, записи для почты) — то значит, таки владелец a.b.c.d не возражает, чтобы его с www.example.com мучали.
Причем, это надо по хорошему делать RFC и реализовывать в браузере, а не отдавать на откуп прикладному уровню. Иначе, получив возможность запустить js в каком-нибудь баннере на достаточно широкой аудитории можно кого угодно за DDoS-ить чисто запросами на подключение.
Получается что автор статьи по-сути придумал вебсокеты над UDP?
А agar.io так часто упоминается скорее всего из-за того что добрая половина всех браузерных игр использует похожий характер сетевых взаимодействий и agar выбрана как «среднестатистическая» браузерка для примера.
Only those users with full accounts are able to leave comments. Log in, please.