【问题标题】:PHP Ratchet Wamp Broadcast to subscribers on publish eventPHP Ratchet Wamp 在发布事件上向订阅者广播
【发布时间】:2016-02-03 08:12:18
【问题描述】:

我正在开发一个 Web 应用程序,在该应用程序中我需要以下场景的实时行为,

应用程序将有两种类型的用户PlayerSpectator。玩家可以加入正在进行的游戏,而观众可以只是旁观。

游戏将由管理员用户初始化。

观众基本上是可以看到加入游戏的人员列表的人。当然,这需要是实时的,当玩家断开连接或新玩家加入游戏时,观众看到实时列表。

总结一下,看看下面的例子

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 joinplayer left 到观众订阅的游戏/主题。

我在服务器端使用Ratchet WebSockets for 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();

【问题讨论】:

  • 那么,问题到底是什么?
  • 首先,-1 代表问题的提出方式(您不是在这里招聘人员)。其次,我看到您正在使用来自 Autobahn 的两个不同版本(实现 WAMP v1 的版本和使用 WAMP v2 的版本)的两种不同语法。 AFAIK,由 Ratchet 中的 WAMPServer 类处理的 PubSub 模式仅与 WAMP v1 兼容,因此您应该只使用 Legacy AutobahnJS。会回来的,因为我也怀疑您实施订阅的方式。
  • @whitelettersinblankpapers 我尝试使用其他语法进行订阅,结果没有什么不同。请检查更新的问题

标签: php ratchet phpwebsocket wamp-protocol


【解决方案1】:

首先,这个答案对你来说可能已经太晚了,尽管我会记录下来。

一旦您在应用程序中建立了多个频道:spectator_GAME_ID

您希望能够看到谁在玩您正在观看的游戏。您使用 WebSocket 的原因是您可以看到实时变化。

你首先要明白Topics都是不同的channels/gameId的。

一旦您意识到这一点并使用棘轮本身示例页面上提供的代码。

    $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。

一旦你有了这个,你就可以只将数据发送给监听某个 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"
}

发送后,您应该在客户端收到它并检查操作,如果操作是“加入”,则将该用户的姓名添加到某个列表中。如果操作是“离开”,则从列表中删除该用户的姓名。

您可以使用一些在更新后调用的函数来更新您在活跃玩家列表中的显示,或者使用 Angular 中的简单 ng-repeat,然后将新值应用于它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-04
    • 2012-02-26
    • 1970-01-01
    • 2015-09-19
    • 1970-01-01
    • 2018-09-05
    • 1970-01-01
    相关资源
    最近更新 更多