PHP игровой сервер, несколько TCP-клиентов?

Я делаю многопользовательскую игру на основе веб-браузера. Я определил, что websockets – лучший способ обработки сообщений, учитывая его природу в реальном времени. Клиент использует холст HTML5, чтобы отобразить игру и веб-сайты для связи с хостом.

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

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

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

Места, где мне нужна помощь:

  • Как найти и назначить порты новым клиентам, уведомить клиента об этом порту и очистить его при отключении.
  • Как это сделать, и все другие транзакции сокетов, не блокируя игровой цикл. Было бы приемлемо принимать сообщения от клиентов в частичных фрагментах и ​​действовать только при полном сообщении.

Может ли кто-нибудь дать мне некоторые технические советы о том, как достичь этих целей? Я не думаю, что все это выглядит слишком много, чтобы спросить PHP, но исправьте меня, если я ошибаюсь!

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

while(gamerunning) { CheckForNewClients(); GetStatusFromClients(); DoGameUpdate(); SendGameStateToClients(); } 

[Обновление] Для всех, кого это интересует, я создал специальное приложение, поддерживающее веб-сокеты (в частности, используя Java и библиотеку веб-сокетов TooTallNates), а не фактический веб-сервис, поскольку, похоже, он имеет больше смысла, хотя, кстати, кажется, что большинство веб-браузеров имеют поскольку в результате проблем с безопасностью возникли сетевые сокеты в корзине.

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

Конечно, вы могли бы попробовать сделать историю 🙂

(пожалуйста, поправьте меня, если я ошибаюсь)

Вам действительно нужно запустить демон PHP, чтобы сделать это эффективно (и ему НУЖНО быть PHP 5.3). Я написал довольно полный обзор использования PHP для процессов демона . Независимо от того, что вы выбрали, я бы предложил вам использовать основанную на событиях систему запуска цикла.

Я разработал базовую библиотеку RunLoop под названием LooPHP, которая, вероятно, может быть полезной, особенно если вы собираетесь иметь дело с *_select . Я был бы более чем счастлив ответить на любой вопрос, который у вас есть об этом.

РЕДАКТИРОВАТЬ:

В системе, основанной на событиях, вы не просто в списке команд, вы реагируете на слушателя. Например…

Вместо того, чтобы делать:

 while( 1 ) { ... /* listen, react */ } /* repeat */ 

Запуск циклов выполняется путем регистрации слушателя (сокетов и других генераторов событий async)

 class ReactClass { ... } $loop = new LooPHP_EventLoop( new ReactClass ); //add one time event $loop->addEvent( function() { print "This event was called 0.5 second after being added\n"; }, 0.5 /* in seconds */ ); //this creates a repeating event, this is called right away and repeats $add_event = function() use ( $loop, &$add_event ) { print "This event is REPEATEDLY called 0.1 every second\n"; $loop->addEvent( $add_event, 0.1 ); }; $add_event(); //start the loop processing, no events are processed until this is done $loop->run(); //php doesn't leave this call until the daemon is done exit(0); //cleanly exit 

Вышеприведенный случай представляет собой очень простой 1 источник EventLoop и вручную добавляет временные функции (их можно добавить даже из вызова ReactClass ).

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

Если вы хотите больше примеров, вы можете найти их в github .

Надеюсь, вы сочтете это полезным.