如何获取特定用户的连接对象?

时间:2013-07-11 02:04:26

标签: php session symfony websocket ratchet

我正在使用 Ratchet 库实时 Symfony 应用,在此应用中,我需要将一些数据发送给特定用户,以便使用逻辑解决方案 SessionProvider ,它将Symfony2 Session对象附加到每个传入的Connection对象。 正如文档所述,我已经设置了一个非本地会话处理程序来存储我的会话,即通过PDO存储在数据库中。 并且目前工作正常,但我需要获取特定用户的Connection对象以向他发送一些数据,因此以其他方式我需要找到引用此用户的连接对象,我找不到办法它? 她是我的服务器代码:

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

2 个答案:

答案 0 :(得分:9)

我自己也有完全相同的问题(减去Symfony),这就是我所做的。

基于hello world tutorial,我用一个数组替换了SplObjectStorage。在介绍我的修改之前,我想评论一下,如果你完成了这个教程并理解了它,那么唯一阻止你自己解决这个问题的方法可能就是不知道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();
    }
}

当然,要使其真正有用,您可能还需要添加数据库连接,并存储/检索这些resourceIds。

答案 1 :(得分:1)

这就是我所做的,对同一个想法有一些改进。

添加了两个可以在别处调用的函数:send_to()和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();
    }
}