это да, тут даже неблокирующий режим не поставлен, не говоря уж о более тонких настройках системных буферов
Вий
> Вот посмотри
> https://gitlab.com/seaice/arctic/-/blob/master/engine/arctic_plat…
> ows_tcpip.cpp
Это ж маленький кусочек, но кода реального сервера? Не выйдет на основе этого куска собрать свой сервер, слишком уж мал фрагмент.
К тому же, только виндовой его части. Наверняка понадобится еще и юниксовый вариант, если речь пойдет о высоких нагрузках. Хотя бы потому, что на аналогичные действия под юниксом уйдет ресурсов в десяток раз меньше.
Вий
> посмотри
но это же ТСР
лучше скажите, может оставить блокирующий сокет и загнать в тред?
тут сокет один и такой вакханалии как у san сделать не получится
Вий
> выбор протокола
это да, но не понимаю как там менеджатся соединения когда клиентов больше одного?
у "гаффера" всё прямо шикарно расписано, единственное код страшный
Вий
> нет понятия соединение
поэтому их эмулируют чтобы понимать от кого чего пришло и кому посылать
https://stackoverflow.com/questions/12404847/knowing-which-udp-client-is-which
https://stackoverflow.com/questions/36263574/how-can-i-identify-p… dp-connection
По udp чаще всего возможно соединить клиентов мимо сервера (p2p). Возможна такая настройка nat, чтобы такое соединение было невозможным, но обычно они так не настроены. Если у кого-то работоспособны торенты, то и p2p для вашей игры будет работать. А у кого не работает, тех можно пустить через сервер, не обязательно через основной, для пересылки можно отдельный иметь.
Zab
Вообще юзайте стимовскую или эпиковскую сеть, оно уже все умеет и пробивать нат и проксить если не пробить.
Эпиковская бесплатная(но без выкладывания в их стор не релизнуть), стимовская "условно" бесплатная и можно не выкладывая в стим релизнуть игру юзая их сеть.
Mephistopheles
Не любой nat можно пробить.
Zab
> Не любой nat можно пробить.
Конечно, вон у мгтс нат не пробивается. По этому я и написал что прокси используют если нат не пробивается. Но это делается прозрачно.
Но чтобы получить непробиваемый nat, с ним должен поработать админ-параноик. Дома у конечного юзера вряд ли такое можно встретить.
Zab
> Но чтобы получить непробиваемый nat, с ним должен поработать админ-параноик.
> Дома у конечного юзера вряд ли такое можно встретить.
у меня дома провайдер мгтс(крупный московский провайдер) и он не пробивается.
Noocrat
Здравствуйте, позвольте мне высказать свое мнение.
Я являюсь С++ разработчиком с 4 летним стажем в backend разработке и большую часть времени я действительно занимался и изучал архитектурны игровых серверов.
Поэтому, я бы хотел дать несколько советов.
Первым шагом можно познакомиться с блогом Гленна Фидлера.
В одной из статей описана реализация сжатия сетевого трафика для input'ов
чтобы уменьшить нагрузку на сеть.
https://gafferongames.com
Но давайте поговорим о жанре MMORPG.
Я бы использовал протокол RUDP (посмотрите на ENet или KCP).
Передавать инпуты для MMORPG жанра не лучшая идея, подумайте о том, чтобы отправлять координаты того, куда игрок переместился с определенной периодичностью, например, позицию, направление взгляда (эти данные также могут быть сжаты)
Чтобы реализовать поддержку большого кол-ва игроков Вам в любом случае понадобится кластеризация, разделите карту на регионы и позвольте каждому серверу обрабатывать свой регион.
Алгоритм quadtree должен подойти для этого.
Кроме того, используя микросервисную архитектуру Вы можете снизить нагрузки с кластеров, позвольте другим микросервисам заниматься гильдиями, чатом и другими вещами.
Такой подход называется параллелизацией на уровне приложений.
При разработке серверов Вы не должны нагружать основной поток тяжелыми операциями, вместо этого используйте дополнительный поток (lock free подход для синхронизации между потоками является самым эффективным).
Теперь, что касается снижения нагрузки на сеть, постарайтесь снизить частоту обновления сущностей, которые не входят в зону интересов игроков.
Ваш сервер также должен иметь приоритеты для обработки игровых данных, например, игроки, которые ничего не делают или находятся в нейтральных городах имеют меньший приоритет на обработку, чем игроки, которые находятся в PvP зонах или участвуют в активных баталиях.
Для больших сетевых пакетов Вы можете применять сжатие (насколько я знаю, самый эффективный способ сжатия - это использовать Oodle Network, но он платный, бесплатный аналог - это lz4),
но проблема в том, что Вы должны будете разобраться в каких случаях сжимать пакет, сжимать маленькие пакеты - это пустая трата CPU и пакет не будет сжат, поэтому вычислите с какого размера стоит начать сжимать пакеты), с учетом использования RUDP - это даст хороший отклик.
По сути, ваша задача - это минимизировать нагрузку на сеть (постарайтесь как можно меньше данных пересылать между сервером и клиентом) и на основной поток каждого кластера.
В совокупности такие подходы должны предоставить Вам возможность поддерживать больше онлайна.
Так же, вы можете взглянуть на https://networknext.com
Автором данного проекта является Гленн Фидлер, это масштабная сеть, которая
реализована для онлайн игр чтобы достичь минимальных задержек за счет лучшей трассировки
сетевого трафика.
IndieDev
> использовал протокол RUDP (посмотрите на ENet или KCP)
даже испугался что за RUDP ещё, мне бы с UDP разобраться
ACK механизм лучше всего у "Гаффера", он избыточный, даже Valve взяли на вооружение, а в ENet ACK может просто потеряться
> сжимать маленькие пакеты - это пустая трата CPU и пакет не будет сжат
пишу сжатие на уровне битов, но да, иногда может выйти хуже чем несжатое, тут просто флажок нужен сжато-несжато
можно даже поставить алгоритм рекомендуемый Гленном в сравнение
https://github.com/rygorous/gaffer_net/blob/master/main.cpp
если разберусь что там происходит
Вий
Для клиент-серверного общения никакой nat punchthrough не требуется, это для P2P общения.
TCP для игр не подходит из-за того, как оно устроено внутри. Кроме того, дополнительные задержки создаются из-за того, что jitter nagle может быть включен.
Если один из ваших пакетов потеряется по пути, то вы заплатите двойную цену за переотправку, так как TCP отбрасывает все что он получил.
В RUDP протокола верхний слой предоставляющий reliable позволяет переотправлять утерянный фрагмент без необходимости отбрасывать все то, что пришло раньше срока.
Реализуйте правильную архитектуру поверх RUDP на основе прокси-пул серверов и никаких проблем у вас не будет, а игрокам станет комфортнее играть.
Я думаю, если клиенты будут посылать пакеты на прокси сервера, то прокси сервера могут сериализовывать все полученные пакеты и пересылать данные одним большим пакетом на соседний микросервис, это что-то вроде следующего:
Client (packets send) -> Proxy (recv small packets)(serialize small packets to one big packet)(send to other service) -> Game server (recv and deserialize).
Тем самым, GameServer'у не требуется вызывать recv часто, так как запросы к ОСи обходятся дорого.
Вий
Вы можете предоставить ссылку на статью об этом?
Насколько мне известно, в клиент-сервер реализациях таких проблем нет, только
если вы забыли отправлять периодический пинг пакеты чтобы NAT сопоставление не прекратилось.
Обычно, это работает следующим образом (поправьте меня если я не прав):
1) Клиент (за NAT) посылает первый пакет на внешний IP:Port (сервер)
2) Роутер создает в памяти сопоставление IP:Port и пересылает пакет в интернет
3) Сервер получает и отвечает клиенту на тот же IP:Port
4) Роутер клиента находит сопоставление и перенаправляет пакет на нужную машину
Если пакет не дошел до клиента, то скорее всего из-за timeout'а роутер удалил сопоставление.
Чтобы этого не происходило нужно обмениваться пинг пакетами.
P.S. Мы не рассматриваем случаи, когда брандмауэр блокирует порты.
Тема в архиве.