2015-11-03 102 views
6

我開發一個Web應用程序,我需要對以下情形的實時行爲,PHP棘輪WAMP廣播給用戶在發佈事件

應用將有兩個類型的用戶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(); 
+0

那麼,究竟是什麼問題呢? – Epodax

+0

首先,-1提問的方式(你不是在這裏招聘人員)。其次,我看到你使用兩種不同版本的Autobahn(實現WAMP v1的版本和使用WAMP v2的版本)的兩種不同語法。 AFAIK,由Ratchet的WAMPServer類處理的PubSub模式只與WAMP v1兼容,因此您只能使用Legacy AutobahnJS。將回來,因爲我也懷疑你實施訂閱的方式。 –

+0

@whitelettersinblankpapers我試圖使用其他語法進行訂閱和結果沒有什麼不同。請檢查更新後的問題 –

回答

1

首先,這答案可能已經太遲了,雖然我會回答記錄。

一旦你已經在你的應用程序建立多種渠道:spectator_GAME_ID

你希望能夠看到誰打你正在看比賽。你使用WebSocket的原因是你可以看到實時變化。

你首先必須明白,主題是所有不同的渠道/ 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的人。


問題的第二部分是向他們發送更新以及如何知道更新是什麼。

最簡單的方法是添加一個字符串,正在發送

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

一旦這個送你應該得到它在客戶方和檢查的動作,如果動作是「加入」的JSON obejct然後將該用戶的姓名添加到某個列表中。如果該行爲是「離開」,則從該列表中刪除該用戶的他/她的名字。

你可以使用一些更新後調用的函數來更新你的顯示在活動播放器列表中,或者使用一個簡單的ng-repeat從角度,然後將新的值應用到它。