2015-06-20 39 views
7

Próbuję zbudować system, w którym użytkownik może zasubskrybować kategorię przy nawiązywaniu połączenia z serwerem websocket, a następnie zacznie otrzymywać aktualizacje dla tej kategorii. Do tej pory pracowałem z Ratchetem i jestem w stanie wysłać wiadomość do wszystkich podłączonych klientów, ale problem polega na tym, że nie chcę wysyłać wiadomości do wszystkich klientów. Chcę tylko wysłać wiadomość do klientów, którzy wykupili konkretna kategoria, w której wiadomości zostały wysłane.Jak wysyłać wiadomości do określonych użytkowników Ratchet PHP Websocket

kod 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(); 
?> 

stronie klienta js kod

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

Odpowiedz

21

Zasadniczo chcesz składni wysyłania danych do WebSocket, polecam koniec, aby to zrobić, używając obiektu JSON. W twojej klasie WebSocket potrzebujesz zmiennej lokalnej o nazwie subscriptions i zmiennej lokalnej o nazwie users, tak jak.

<?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, żeby pójść z tym wygląda trochę jak ten

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

Uwaga: Ten kod jest niesprawdzone pisałem go w locie z mojego doświadczenia z grzechotką. Powodzenia :)

+0

Właściwie muszę użyć Ratchet Pusher. I zrobiłem, że wszystko działa dobrze, ale teraz problem polega na tym, że klient zostaje rozłączony po kilku minutach bezczynności bez żadnego komunikatu o rozłączeniu, że przestaje odbierać wiadomość. Jeśli ciągle wysyłam wiadomości do klienta co 10 minut, to się nie rozłącza, ale jeśli istnieje luka trwająca ponad 20 minut, klient nie otrzymuje wiadomości. –

+0

@RohitKhatri, czego używasz do łączenia się z websocket? Czy pośredniczysz w tym poprzez nginx czy coś takiego? – MarshallOfSound

+0

Używam Ratchet z Pusher z tego przykładu [link] (http://socketo.me/docs/push) –