2013-07-11 11 views
8

Sto lavorando in un tempo reale Symfony applicazione utilizzando Ratchet biblioteca, in questa applicazione ho bisogno di inviare alcuni dati di un utente specifico per cui la soluzione logica era quella di utilizzare il SessionProvider che associare un oggetto Symfony2 Session a ciascun oggetto Connection in ingresso. Come afferma la documentazione, ho impostato un gestore di sessione non nativo per memorizzare le mie sessioni, ad esempio in un database tramite PDO. e che funziona bene per il momento, ma ho bisogno di ottenere l'oggetto Connection di un utente specifico per inviarlo alcuni dati così in altro modo ho bisogno di trovare l'oggetto di connessione che fa riferimento a questo utente e non riesco a trovare un modo per fallo ? lei è il mio codice del server:come ottenere l'oggetto di connessione di un utente specifico?

$app=new AggregateApplication(); 
    $loop = \React\EventLoop\Factory::create(); 
    $context = new \React\ZMQ\Context($loop); 
    $pull = $context->getSocket(\ZMQ::SOCKET_PULL); 
    $pull->bind('tcp://127.0.0.1:5555'); 
    $pull->on('message', array($app, 'onNotification')); 
    $webSock = new \React\Socket\Server($loop); 
    $webSock->listen(8080, '127.0.0.1'); 
    $handler = $this->getContainer()->get('session.handler'); 
    $server=new \Ratchet\Wamp\WampServer($app); 
    $server = new SessionProvider($server, $handler); 
    $webServer = new \Ratchet\Server\IoServer(new \Ratchet\WebSocket\WsServer($server),$webSock); 
    $loop->run(); 
+0

Ma come inviare un messaggio a un utente specifico? Come implementarlo nell'esempio di 2 client connessi a un server WebSocket, ciascuno con il proprio oggetto di connessione: $ ConnSender, $ ConnReceiver? Per favore, per chiarire a me non trovo alcuna risposta a questo sul tag ratchet di SO.thanks –

+0

ogni volta che un utente è connesso al server webs Prendo il suo ID e memorizzo il suo oggetto di connessione in un array indicizzato con il suo ID quindi, quando voglio inviare alcuni dati a quel client, ottengo il suo oggetto di connessione usando il suo ID e io lo uso per inviare i miei dati. –

+0

Capisco cosa intendi, ma per favore lasciami aggiungere un'altra domanda perché non è chiara per me. Quando avrò il mio array contenente due oggetti di connessione con due ID diversi (Id1 di mittente e Id2 di ricevitore), in che modo il server WebSocket otterrà Id2 per inviargli il messaggio? '$ client = $ this-> clients [$ Id2]; $ client-> send (" Message ");' –

risposta

8

ho avuto la stessa identica domanda che mi (meno Symfony) e qui è quello che ho fatto.

In base allo hello world tutorial, ho sostituito SplObjectStorage con un array. Prima di presentare le mie modifiche, vorrei commentare che se hai seguito questo tutorial e l'hai capito, l'unica cosa che ti ha impedito di arrivare a questa soluzione da solo probabilmente non è sapere cosa sia SplObjectStorage.

class Chat implements MessageComponentInterface { 
    protected $clients; 

    public function __construct() { 
     $this->clients = array(); 
    } 

    public function onOpen(ConnectionInterface $conn) { 
     // Store the new connection to send messages to later 
     $this->clients[$conn->resourceId] = $conn; 
     echo "New connection! ({$conn->resourceId})\n"; 
    } 

    public function onMessage(ConnectionInterface $from, $msg) { 
     $numRecv = count($this->clients) - 1; 
     echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n" 
      , $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's'); 

     foreach ($this->clients as $key => $client) { 
      if ($from !== $client) { 
       // The sender is not the receiver, send to each client connected 
       $client->send($msg); 
      } 
     } 
     // Send a message to a known resourceId (in this example the sender) 
     $client = $this->clients[$from->resourceId]; 
     $client->send("Message successfully sent to $numRecv users."); 
    } 

    public function onClose(ConnectionInterface $conn) { 
     // The connection is closed, remove it, as we can no longer send it messages 
     unset($this->clients[$conn->resourceId]); 

     echo "Connection {$conn->resourceId} has disconnected\n"; 
    } 

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

     $conn->close(); 
    } 
} 

Naturalmente per renderlo veramente utile si può anche voler aggiungere in una connessione DB, e memorizzare/recuperare quei resourceIds.

+0

Pensa che ho già questa soluzione, ma mi chiedo solo perché nel documento ufficiale di Rachet hanno detto che dobbiamo collegare ogni oggetto di connessione a una sessione di symfony usando il gestore di sessione ... Se possiamo farlo usando semplicemente sqlObjectStorage e Id dei clienti? –

+0

Penso che intendano questo: "fornisci accesso in sola lettura ai dati della sessione dal tuo sito web". –

+1

Cosa succede se cambio i resourceIds stessi? Ecco cosa sto facendo: ogni volta che stabilisco una connessione, invio immediatamente un messaggio che ha l'id effettivo di quell'utente (non la sua resourceId, sto parlando dell'ID che uso per recuperare il nome, il cognome, ecc. Dell'utente), e quindi dopo aver ricevuto il messaggio, ho cambiato il resourceId dell'utente con l'id che ho inviato con il messaggio, e poi ogni volta che voglio inviare a quell'utente un messaggio, fondamentalmente faccio un loop attraverso lo storage spl e quando trovo una corrispondenza con il suo id, gli mando il messaggio. Dovrei farlo? È sicuro sostituire resourceIds? – Taurus

0

questo è quello che ho fatto, ha alcuni miglioramenti sulla stessa idea.

aggiunge 2 funzioni che è possibile chiamare altrove: send_to() e multicast().

namespace mine; 
use Ratchet\MessageComponentInterface; 
use Ratchet\ConnectionInterface; 

class ws implements MessageComponentInterface { 
    protected $clients; 
    protected $clientids; 

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

    public function multicast($msg) { 
     foreach ($this->clients as $client) $client->send($msg); 
    } 

    public function send_to($to,$msg) { 
     if (array_key_exists($to, $this->clientids)) $this->clientids[$to]->send($msg); 
    } 

    public function onOpen(ConnectionInterface $conn) { 
     $socket_name = "{$conn->resourceId}@{$conn->WebSocket->request->getHeader('X-Forwarded-For')}"; 
     $this->clients->attach($conn,$socket_name); 
     $this->clientids[$socket_name] = $conn; 
    } 

    public function onMessage(ConnectionInterface $from, $msg) { 
     $this->multicast($msg); 
    } 

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

    public function onError(ConnectionInterface $conn, \Exception $e) { 
     $conn->close(); 
    } 
} 
Problemi correlati