2015-06-20 17 views
7

Ich versuche, ein System zu erstellen, wo Benutzer eine Kategorie beim Herstellen der Verbindung zum Websocket-Server abonnieren können und dann wird er Updates für diese Kategorie erhalten. Bis jetzt habe ich mit Ratchet gearbeitet und bin in der Lage, Nachrichten an alle angeschlossenen Clients zu senden, aber das Problem ist, dass ich keine Nachricht an alle Clients senden möchte, die ich nur an die Kunden senden möchte, die das Abonnement abonniert haben die bestimmte Kategorie, in der die Nachrichten gesendet wurden.So senden Sie Nachrichten an bestimmte Benutzer Ratchet PHP Websocket

PHP-Code

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

Client-Seite js Code

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

Antwort

21

Grundsätzlich wollen Sie eine Syntax für das Senden von Daten zu der WebSocket, empfehle ich Beenden Sie dazu ein JSON-Objekt. In Ihrer WebSocket-Klasse benötigen Sie eine lokale Variable namens subscriptions und eine lokale Variable namens 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(); 
    } 
} 
?> 

Die Javascript damit gehen sieht ein bisschen wie dieser

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

Hinweis: Dieser Code ungetestet ich es on the fly aus meiner Erfahrung mit Knarre schrieb. Viel Glück :)

+0

Eigentlich muss ich Ratchet Pusher verwenden. Und ich habe getan, dass alles gut funktioniert, aber jetzt ist das Problem, dass der Client die Verbindung trennt, nachdem er einige Minuten im Leerlauf war, ohne dass eine Nachricht unterbrochen wurde. Wenn ich in Abständen von 10 Minuten weiterhin Unordnung an den Client sende, wird die Verbindung nicht unterbrochen, aber wenn eine Lücke von mehr als 20 Minuten besteht, erhält der Client keine Nachricht. –

+0

@RohitKhatri Was verwenden Sie, um eine Verbindung zum Websocket herzustellen? Bevollmächtigen Sie es durch Nginx oder etwas? – MarshallOfSound

+0

Ich benutze Ratchet mit Pusher aus diesem Beispiel [link] (http://socketo.me/docs/push) –

Verwandte Themen