PHP Ratchet Wamp Broadcast подписчикам в событии публикации

Я разрабатываю веб-приложение, в котором мне нужно поведение в реальном времени для следующего сценария:

Приложение будет иметь два типа пользователей Player и Spectator. Игроки могут присоединиться к идущей игре, а зрители могут просто наблюдать.

Игра будет инициализирована пользователем с правами администратора.

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

Подводя итог, рассмотрим приведенный ниже пример.

Spectator_1 joins Clan_101 
Spectator_2 joins Clan_201

Player_1 joins Clan_101 // Need to broadcast this event to Spectator_1
Player_2 joins Clan_101 // Need to broadcast this event to Spectator_1
Player_1 disconnects Clan_101 // // Need to broadcast this event to Spectator_1

Player_11 joins Clan_201 // Need to broadcast this event to Spectator_2
Player_12 joins Clan_201 // // Need to broadcast this event to Spectator_2

Рассматривая текущую игру как тему/канал (Ratchet\Wamp\Topic), мне нужно транслировать зрителям следующие события player join и player left в игру/тему, на которую подписаны зрители.

Я использую Ratchet WebSockets для PHP на стороне сервера и autobahn js на стороне клиента

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

player.html

<script src="scripts/autobahn.js" type="text/javascript"></script>
<script src="scripts/jquery-1.11.2.min.js" type="text/javascript"></script>
<script>
ab.connect(
    'ws://localhost:8080',
     function (session) {
         appSession = session;
         $('#btnJoinGame').on('click',function(){
         session.publish('joingame', ['data','GAME_ID']);
     });                   
 });
</script>

spectator.html

<script>
var conn = new ab.Session(
    'ws://localhost:8080', 
    function() {            
         conn.subscribe('spectator_GAME_ID', function(topic, data) {
            console.log(topic);
            console.log(data);
         });
     },
     function() {            
        console.warn('WebSocket connection closed');
     }    
 );  
 /* OR Using the legacy syntax */
 /*
     ab.connect(
         'ws://localhost:8080',
          function (session) {
              session.subscribe("t1011", function (topic, event) {
                  console.log(event);
              });
          }                       
      );
 */
</script>

Server.php

require __DIR__ . '/vendor/autoload.php';

use Ratchet\Wamp\WampServerInterface;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface as Conn;


class EventHandler implements WampServerInterface, MessageComponentInterface{
     public function __construct(React\EventLoop\StreamSelectLoop $loop){
        $this->loop = $loop;
     }
     public function onSubscribe(Conn $conn, $subscription, $params = array()){   
        $subscription->broadcast($this->data);
     }

     public function onPublish(Conn $conn, $topic, $params, array $exclude, array $eligible) {
        if($topic->getId() === 'joingame'){
            if(!isset($this->data[$params[1]])){
                $this->data[$params[1]] = array($params[0]);
            }else{
                array_push($this->data[$params[1]], $params[0]);
            }            
        }
        /** DOES'NT WORKS **/
        $newtopic = new Ratchet\Wamp\Topic('spectator_GAME_ID');
        $this->onSubscribe($conn,$newtopic);
    }
    /*Omitting other methods for brevity*/
}

$loop   = React\EventLoop\Factory::create();

$webSock = new React\Socket\Server($loop);
$webSock->listen(8080, '0.0.0.0'); // Binding to 0.0.0.0 means remotes can connect
new Ratchet\Server\IoServer(
    new Ratchet\Http\HttpServer(    
        new Ratchet\WebSocket\WsServer(
            new Ratchet\Wamp\WampServer(
                new EventHandler($loop) // This is my class. Pass in the loop!
            )
        )
    ),
    $webSock
);

$loop->run();

person hitesh israni    schedule 03.11.2015    source источник
comment
Так в чем собственно вопрос?   -  person Epodax    schedule 03.11.2015
comment
Во-первых, -1 за то, как был задан вопрос (вы здесь не нанимаете людей). Во-вторых. Я вижу, что вы используете два разных синтаксиса из двух разных версий Autobahn (версия, реализующая WAMP v1, и версия, использующая WAMP v2). Насколько мне известно, шаблон PubSub, обрабатываемый классом WAMPServer в Ratchet, совместим только с WAMP v1, поэтому вам следует использовать только Legacy AutobahnJS. Вернусь, потому что я тоже сомневаюсь в том, как вы реализовали подписку.   -  person Adib Aroui    schedule 11.11.2015
comment
@whitelettersinblankpapers Я пытался использовать другой синтаксис для подписки, и результат не отличается. пожалуйста, проверьте обновленный вопрос   -  person hitesh israni    schedule 14.11.2015


Ответы (1)


Прежде всего, этот ответ, вероятно, уже слишком запоздал для вас, хотя я отвечу на него для протокола.

После того, как вы установили несколько каналов в своем приложении: spectator_GAME_ID

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

Прежде всего, вы должны понимать, что все темы — это разные каналы/идентификаторы игр.

Как только вы это осознаете и воспользуетесь кодом, приведенным на странице примера самого храповика.

    $entryData = json_decode($entry, true);

    // If the lookup topic object isn't set there is no one to publish to
    if (!array_key_exists($entryData['category'], $this->subscribedTopics)) {
        return;
    }

    $topic = $this->subscribedTopics[$entryData['category']];

    // re-send the data to all the clients subscribed to that category
    $topic->broadcast($entryData);

В своем примере они используют категории в своей строке JSON, вы, вероятно, измените это на gameId.

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


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

Самый простой способ — добавить строку в отправляемый объект JSON.

{
     "action": "join",
     "gameId": "123",                  //so that you know to which game to publish it
     "userIdThatJoined": "123456789",  //whatever other data you need
     "userNameThatJoined": "Foo Bar"
}

Как только это будет отправлено, вы должны получить его на стороне клиента и проверить действие, если действие «присоединиться», затем добавить имя этого пользователя в какой-либо список. Если действие «уйти», то удалите имя этого пользователя из списка.

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

person mitchken    schedule 10.05.2016