2015-06-20 3 views
7

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

PHP код

Chat.php

<?php 
namespace MyApp; 
use Ratchet\MessageComponentInterface; 
use Ratchet\ConnectionInterface; 

class Chat implements MessageComponentInterface 
{ 
    protected $clients; 

    public function __construct() 
    { 
     $this->clients = new \SplObjectStorage; 
    } 

    public function onOpen(ConnectionInterface $conn) 
    { 
     $this->clients->attach($conn); 
    } 

    public function onMessage(ConnectionInterface $conn, $msg) 
    { 
     foreach ($this->clients as $client) 
     { 
      if($conn !== $client) 
       $client->send($msg); 
     } 
    } 

    public function onClose(ConnectionInterface $conn) 
    { 
     $this->clients->detach($conn); 
    } 

    public function onError(ConnectionInterface $conn, \Exception $e) 
    { 
     echo "An error has occurred: {$e->getMessage()}\n"; 
     $conn->close(); 
    } 
} 
?> 

server.php

<?php 
use Ratchet\Server\IoServer; 
use Ratchet\Http\HttpServer; 
use Ratchet\WebSocket\WsServer; 
use MyApp\Chat; 

require dirname(__DIR__) . '/Ratchet/vendor/autoload.php'; 

$server = IoServer::factory(
    new HttpServer(
    new WsServer(
     new Chat() 
    ) 
), 
    8080 
); 

$server->run(); 
?> 

стороне клиента код расслоение плотной

<script type="text/javascript"> 
var conn = new WebSocket('ws://localhost:8080'); 

conn.onopen = function(e) { 
    console.log("Connection established!"); 
}; 

conn.onmessage = function(e) { 
    console.log(e.data); 
}; 
</script> 

ответ

21

В основном вы хотите синтаксис для отправки данных WebSocket, я повторяю с помощью объекта JSON для этого. В вашем классе WebSocket вам нужна локальная переменная с именем subscriptions и локальная переменная с именем users.

<?php 
namespace MyApp; 
use Ratchet\MessageComponentInterface; 
use Ratchet\ConnectionInterface; 

class Chat implements MessageComponentInterface 
{ 
    protected $clients; 
    private $subscriptions; 
    private $users; 

    public function __construct() 
    { 
     $this->clients = new \SplObjectStorage; 
     $this->subscriptions = []; 
     $this->users = []; 
    } 

    public function onOpen(ConnectionInterface $conn) 
    { 
     $this->clients->attach($conn); 
     $this->users[$conn->resourceId] = $conn; 
    } 

    public function onMessage(ConnectionInterface $conn, $msg) 
    { 
     $data = json_decode($msg); 
     switch ($data->command) { 
      case "subscribe": 
       $this->subscriptions[$conn->resourceId] = $data->channel; 
       break; 
      case "message": 
       if (isset($this->subscriptions[$conn->resourceId])) { 
        $target = $this->subscriptions[$conn->resourceId]; 
        foreach ($this->subscriptions as $id=>$channel) { 
         if ($channel == $target && $id != $conn->resourceId) { 
          $this->users[$id]->send($data->message); 
         } 
        } 
       } 
     } 
    } 

    public function onClose(ConnectionInterface $conn) 
    { 
     $this->clients->detach($conn); 
     unset($this->users[$conn->resourceId]); 
     unset($this->subscriptions[$conn->resourceId]); 
    } 

    public function onError(ConnectionInterface $conn, \Exception $e) 
    { 
     echo "An error has occurred: {$e->getMessage()}\n"; 
     $conn->close(); 
    } 
} 
?> 

Javascript, чтобы пойти с этим выглядит немного как этот

<script type="text/javascript"> 
var conn = new WebSocket('ws://localhost:8080'); 

conn.onopen = function(e) { 
    console.log("Connection established!"); 
}; 

conn.onmessage = function(e) { 
    console.log(e.data); 
}; 

function subscribe(channel) { 
    conn.send(JSON.stringify({command: "subscribe", channel: channel})); 
} 

function sendMessage(msg) { 
    conn.send(JSON.stringify({command: "message", message: msg})); 
} 
</script> 

Примечание: Этот код тестировался я написал его на лету из моего опыта с реверсом. Удачи :)

+0

На самом деле мне нужно использовать Ratchet Pusher. И я сделал это, все работает нормально, но теперь проблема в том, что клиент отключается после нескольких минут бездействия без какого-либо сообщения об отключении, он перестает получать сообщение. Если я продолжаю отправлять messing клиенту каждые 10 минут, он не отключается, но если есть пробел, как более 20 минут или около того, клиент не получает сообщение. –

+0

@RohitKhatri, что вы используете для подключения к websocket? Проксируете ли вы его через nginx или что-то в этом роде? – MarshallOfSound

+0

Я использую Ratchet с Pusher из этого примера [ссылка] (http://socketo.me/docs/push) –