Ratchet WebSocket Server 可以向客户端本身发送消息吗?

Posted

技术标签:

【中文标题】Ratchet WebSocket Server 可以向客户端本身发送消息吗?【英文标题】:Can Ratchet WebSocket Server send a message to client itself? 【发布时间】:2012-10-04 04:32:23 【问题描述】:

我想使用 Ratchet (http://socketo.me) 在 iPhone 应用程序和服务器之间建立永久连接。我需要在应用程序和服务器之间交换数据。

从这个例子 (http://socketo.me/docs/hello-world) 我发现我有一个函数 onMessage 当应用程序向服务器发送消息并且服务器可以向服务器发送响应时将调用它应用程序。

但服务器还必须能够在不从应用程序获取数据的情况下向应用程序发送数据。例如,应用程序和服务器之间的连接已经建立。服务器上发生了一些事情,我们需要向应用程序发送新数据。我该怎么做?有可能吗?

主要问题是如何从服务器向应用程序发送数据?

感谢您的帮助。

【问题讨论】:

【参考方案1】:

这确实是可能的。您需要以某种方式与 WebSocket 服务器进程进行通信。您可以通过使用某种形式的消息传递来做到这一点,无论是 RPC 还是消息队列。

Ratchet 本身基于 React 事件循环。这意味着与 Ratchet 的任何形式的通信都必须与该事件循环集成。 On the React homepage你可以看到一些已经存在的集成:

Predis/Async(可以使用 redis pub/sub 进行消息传递) DNode-php(dnode 是一个基于 TCP 的 RPC 协议) React/ZMQ(与ZeroMQ集成事件循环) React/Stomp(STOMP协议的实现,让你可以和RabbitMQ这样的消息对话) JCook21/ReactAMQP(React PHP 的 AMQP 绑定)

在 Ratchet 文档中有 a tutorial on how to use React/ZMQ 以便将消息从任何地方推送到您的 WebSocket 服务器。

【讨论】:

React/ZMQ 的好例子。但我不知道如何将正确的数据(例如,我创建的特殊 json)推送给正确的用户。例如,我必须将数据发送给正确的用户(我有用户 ID 列表)。用户是否有必要订阅“特定页面”(就像他们在这里说的:socketo.me/docs/push)? igorw,云我们以某种方式连接(例如,Skype)直接向您提问。并感谢您的帮助。 irc.freenode.net 上有一个#reactphp IRC 频道。【参考方案2】:

Ratchet 还实现了 WAMP,其中包括 PubSub。因此,您的客户可以订阅某些主题,并且您可以让其他客户端(即在您的后端基础架构上运行)发布到这些主题。您可以让基于 AutobahnPython 的客户端通过 Ratchet 发布到基于 Autobahnandroid 的移动应用程序或基于 AutobahnJS 的 html5 客户端。

【讨论】:

它使用 wampv1 ,ios 没有 v1 的库。有没有办法使用 MessageComponent Interface 进行推送? Thruway 支持 WAMPv2 github.com/voryx/Thruway,所以你应该可以使用 github.com/mogui/MDWamp 与它【参考方案3】:

我有完全相同的问题,这就是我所做的。

基于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();
    

当然,为了让它真正有用,您可能还想添加一个数据库连接,并存储/检索这些资源 ID。

【讨论】:

效果很好!但这有点像ack,一旦服务器收到一条消息,您就向客户端发送一条消息。如何在不从客户端获取消息的情况下向客户端发送(启动)消息

以上是关于Ratchet WebSocket Server 可以向客户端本身发送消息吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用 stunnel 和 Ratchet 保护 websocket。连接已关闭

React/ZMQ/Ratchet - Websocket 服务器响应

树莓派的 Ratchet Websocket

使用 Ratchet for PHP 通过 WebSocket 流式传输二进制数据

Javascript 无法连接到 PHP Ratchet WebSocket 服务器

在 Debian 上运行的 Ratchet PHP Websocket