Player.IO. Сетевые архитектуры

Сегодня мы рассмотрим сетевые архитектуры для онлайн игр и поговорим об их плюсах и минусах.

Под сетевой архитектурой подразумевается способ подключения и общения клиентов (компьютеров игроков) между собой в многопользовательских играх. Как правило, для игр используется два способа подключения это: Peer-To-Peer и Client-Server.

Peer-To-Peer архитектура

Под Peer-To-Peer (P2P) архитектурой подразумевается, что каждый из компьютеров подключается в общую сеть, и каждый компьютер имеет контроль над данными игры. Так же в такой архитектуре может присутствовать и сервер, но тут он используется только как посредник для передачи данных.

Основная проблема P2P заключается в безопасности, вернее в отсуствии какой-либо безопасности вообще. То есть P2P — это невероятные возможности для хакера! Одним словом: золотая жила для читов и самоутверждения недобросовестных игроков. Но самое ужасное заключается в том, что используя P2P, мы не имеем почти никаких возможностей противостоять хакерам и читерам.

Давайте рассмотрим пример: два игрока играют в пошаговую игру, где каждый из них должен нападать на другого в свою очередь. Пусть первый игрок будет у нас хакером. Наступает ход первого игрока, он должен нанести некий произвольный урон второму игроку. То есть, на клиенте первого игрока вычисляется какой-то случайный урон, который отправляется второму игроку. Но поскольку это происходит локально, на машине хакера, то фактически он обладает этими данными и может подменить их. ?, опа! Второй игрок получает 9999 урона и проигрывает. Хакер писается от счастья!

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

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

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

Впрочем все эти примеры — это только верхушка айсберга проблем с P2P. ? теперь мы можем с уверенностью сказать что P2P не самое лучшее решение для онлайн игр. Пожалуй, единственный случай, когда вам следует использовать P2P архитектуру — это если вы не можете или не хотите создавать сервер.

Помните, в самом начале я писал о том, что вы можете использовать и Player.IO для создания многопользовательских игр с использованием подключения по P2P? Так вот, достаточно просто указать «Bounce» при подключении или создании игровой комнаты, и тогда все сообщения, отправляемые вами на сервер будут просто пересланы другим подключенным клиентам:

client.multiplayer.createJoinRoom([roomName], "Bounce", [restParams]);

Двухуровневая система

Возвращаясь к вопросу безопасности, если мы не можем доверять нашим клиентам, то кому же мы можем тогда доверять? Конечно, серверу! Если у вас есть сервер, на котором принимаются все решения на основе данных от клиентов, то можно сказать, что вы отняли у хакеров основные возможности для самореализации. ? это подводит нас к двухуровневой архитекутре, где сервер — это больше, чем просто почтальен. Он выполняет игровую логику и рассчитывает всю важную информацию. С таким подходом у нас получается уже две программы и код в двух местах. Давайте посмотрим, как это будет выглядеть:

Обратите внимание, только сервер и пользователь важны для правильной работы нашей игры, и это дает интересные последствия.

Наш клиент зажат между пользователем и сервером, на котором в действительности происходит игра, и пользователем, который активирует какие-либо действия. Клиент-же в данном случае используется только для одной цели: обеспечивает связь между игроком и сервером. То есть наша флеш игра не более, чем средство для получения и отправления информации на сервер.

Таким образом клиент имеет две задачи:

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

 

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

Client-Server архитектура

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

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

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

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

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

Здесь хочется отметить очень важный момент защиты игры: всегда проверяйте то, что действие, выполняемое игроком, корректно и допустимо. Если вы думаете, что защищены и уверены в том, что никогда не получите от клиента неправильных данных, то не забывайте, что всегда может случится что-то непредсказуемое и игровой процесс может быть разрушен.

Теперь давайте еще раз вернемся к примеру с шашками и рассмотрим его с использованием клиент-серверной архитектурой.

?грок хочет выполнить ход от A2 до C4. Как и прежде он должен отправить следующее сообщение серверу, чтобы сообщить о своих действиях:

connection.send("move", 1, 2, 3, 4);

Отправить сообщение о ходе игрока — это все, что мы должны сделать. Больше ничего не нужно делать, пока не получим от сервера сообщение о том, что ход выполнен.

Получив сообщение от клиента на севере, мы убедились, что ход игрока допустим и соотвествует правилам игры, и только тогда осуществляем перемещение фишки, отправляя всем игрокам сообщение о выполненом ходе, в том числе и для игрока, который выполнил ход. Сообщение о выполненом ходе всем игрокам можно отправить такой строкой:

broadcast("move", 1, 2, 3, 4);

Возвращаясь к клиенту: мы получаем сообщение от сервера в котором говорится, что мы должны переместить фишку из клетки (1,2) в клетку (3,4). К счастью, команду сервера мы должны выполнить обязательно, и так же будет каждый раз, когда какой-либо другой игрок сделает свой ход.

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

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

Это вольный перевод статьи: «Building Flash Multiplayer Games — Network Architectures»

Содержание

  1. Как создать онлайн игру? Анонс
  2. Player.IO. Введение
  3. Player.IO. Основы или первая онлайн игра
  4. Player.IO. Пошаговые игры
  5. Player.IO. Сетевые архитектуры
  6. Player.IO. Безопасность в онлайн играх
  7. Player.IO. Пример пошаговой игры
  8. Player.IO. Онлайн игры в реальном времени
  9. Player.IO. Синхронизация игроков
  10. Player.IO. ?нтерполяция или удивительный мир обмана
  11. Player.IO. Решение проблемы задержек
  12. Player.IO. Советы и рекомендации

 

 

Спасибо за урок. Пока все просто, доступно и понятно.
А сколько всего таких уроков будет?

Андрей
20 Октября 2012
— 02:09
#

@Андрей, еще 8 уроков. С пошаговыми играми все относительно просто, а вот про игры в реальном времени будет более интересная информация :)

Ant.Karlov
20 Октября 2012
— 02:30
#

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

WeslomPo
20 Октября 2012
— 10:04
#

Вопросы честности генерации случайных значений решаются протоколами асимметричного шифрования. Вот, например, в третьем разделе можно посмотреть пример протокола игры в покер по телефону (стационарному): http://yury.name/crypto/02cryptonote.pdf

"Странные противоречия" решаются точно так же как и в серверной архитектуре: предсказание состояния, синхронизация, коррекция/интерполяция.

Claymore
20 Октября 2012
— 11:11
#

Предыдущий коммент к P2P

Claymore
20 Октября 2012
— 11:20
#

@Claymore,

> "Странные противоречия" решаются точно так же как и в серверной архитектуре: предсказание состояния, синхронизация, коррекция/интерполяция.

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

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

Ant.Karlov
20 Октября 2012
— 15:03
#

>в итоге мы поимеем кучу проблем при реализации всех этих предсказаний и синхронизаций.

Так и в случае с сервером придется все это реализовывать, если синхронный геймплей. Вот неплохая статья для понимания принципов - http://habrahabr.ru/post/135306

> небольшим количеством одновременно играющих игроков

Согласен. Лучше всего подходит для PvP игр вроде Worms. Для реализации кооперативного режима игры, так вообще идеальный вариант, по-моему, и отпадает вопрос контроля честности (Даешь! Третий Зомботрон с режимом на двух игроков, один играет за чувака из первой части, другой за чувака из второй ;D). Плюсы P2P - сокращение расходов на поддержку сервера, сокращение задержки (если игроки находятся географически близко, то реально ощутимо), можно делать всякие штуки с распределенными вычислениями, в общем есть свая сфера применения.

Claymore
20 Октября 2012
— 16:30
#

@Claymore, если даже работать с P2P то я бы в таком случае тоже настаивал бы на клиент-серверной модели, то есть когда один из клиентов становится сервером. Но даже если забить на проблемы с синхронизацией и безопасности данных, то как игроки будут коннектится друг к другу в случае веб-игрушек? То есть как Вася Пупкен соединится с Клавой Петровой, чтобы зарубится на пять минут!?

То есть в случае с веб-играми (флешечками в частности), я считаю, что без сервера действительно будет все плохо.

> можно делать всякие штуки с распределенными вычислениями

С клиент-серверной архитектурой тоже можно так же извратится :) Отдавать некоторые произвольные вычисления клиентам.

Ant.Karlov
20 Октября 2012
— 20:05
#

@Ant.Karlov
>Но даже если забить на проблемы с синхронизацией и безопасности данных

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

>то как игроки будут коннектится друг к другу в случае веб-игрушек? То есть как Вася Пупкен соединится с Клавой Петровой, чтобы зарубится на пять минут!?

Через Cirrus или свой RTMFP сервак поднять если есть желание, по локалке можно просто через мультикаст без серваков. Коммуникация игроков как обычно, комнаты + чатики через p2p или сервак , или заранее договариваются о названии группы.

Claymore
21 Октября 2012
— 00:48
#

>то как игроки будут коннектится друг к другу в случае веб-игрушек? То есть как Вася Пупкен соединится с Клавой Петровой, чтобы зарубится на пять минут!?

Антон, ты недооцениваешь возможности P2P архитектуры. Я сейчас делаю сетевую игру, где сервер используется только для базы данных об игроках. Для самого взаимодействия между игроками (поиск соперника, подключение, игра) используется P2P фреймворк as3mul.

ggman
21 Октября 2012
— 01:04
#

А на Player.IO есть поддержка mySQL или других СУБД? ?ли это придётся реализовывать отдельно?

Владимир
21 Октября 2012
— 10:02
#

@Владимир, вам сюда:
http://playerio.com/documentation/bigdb/
и
http://playerio.com/documentation/bigdb/example

@Ant.Karlov, отличные уроки на больную тему, жаждим продолжение :)

o_OKazan
21 Октября 2012
— 10:22
#

На тему безопасности. У нас в СНГ очень много читеров. ?гру будут пытать и мучить всеми доступными средствами. P2P подходит в одном и только в одном случае - кооператив без каких либо сохранений результатов. Как только появляется намек на сохранение достижений или (обоже!) рпг систему, то все, P2P летит к черту - игру сломают через 5 минут после выхода.
Тоже самое с PvP режимами. Думаю не зря Valve отказались от P2P в Доте2.

Izmy
22 Октября 2012
— 16:10
#

Основная цель централизации классического немассового мультиплеера - это борьба с пиратством и/или интегрирование free-to-play модели. Для такого класса игр, сама по себе, серверная архитектура не дает какого-то мега профита в технической борьбе с читерами. Основной метод борьбы как раз административный – бан аккаунтов, ну, и детектирование, контроль целостности, и патчинг дыр. Всегда остаются клиент-сайд читы: мапхакинг (убрать туман войны, например), автоприцеливание, боты, etc.

Я ведь тут не стараюсь пропагандировать p2p, в большинстве случаев при наличии необходимых средств и ресурсов серверная реализация, полностью или частично, будет выглядеть предпочтительней. Просто в выборе нужно исходить из задач и имеющихся ресурсов, хорошенько все взвесив. Ясен пень, что в официальном туторе к Player.IO тебе расскажут: «p2p – мрак, арендуй сервер, заноси деньги к нам» - лучше бы учили оптимизировать трафик и нагрузку, чтобы расходы сократить.
Я вот не вижу каких-то значительных препятствий в том, чтобы в игре типа Castle crashers, или в тактической схватке вроде Hero academy, дать игрокам возможность играть по локальной сети или напрямую, посредством p2p. Можно и оба варианта (и глобальный сервер, и p2p) реализовать, предоставив выбор игрокам, можно скомбинировать, чтобы снизить нагрузку на сервер, не обязательно же все лбами сталкивать. Особенно в масштабе портальных флешек, архитектура p2p вполне себе актуальна. Ну, а читинг он всегда был и будет. В каждой десятой (условно) портальной флешке, есть глобальная система очков, и, естественно, там ни без читеров, но это же не заставляет разработчиков бить тревогу и бежать в Player.IO за серверными решениями проблем – потому что нецелесообразно, для p2p-режима на пару(несколько) человек уровень тревоги примерно такой же, по-моему - ну, немного протоколы подкрутить и совсем уж явные пути купировать.

З.Ы. В доте 2, вроде бы заявлена поддержка лана в будущем, в такой микрозависимой игре пинг критичен, скорей всего сделают. Тем более 10 человек, в СК2 два - и то фейлы случаются с батллнетом, на турнирах мирового уровня.

Claymore
22 Октября 2012
— 22:03
#

2Claymore Наверно для ЕвропыСША действительно P2P во многих случаях эффективнее. Но у нас в Эрэфии у каждого третьего школьника установлены всякие MonsterDebugger, CheatEngine и прочие гадости. Сложно не стать в таких условиях параноиком, особенно если игра ориентирована на микроплатежи. Кстати с клиент-сайд читами тоже можно бороться с помощью сервера.

Izmy
22 Октября 2012
— 23:26
#