将消息从 PHP 脚本发送到多个 Ratchet Websocket 应用程序(通过 ZMQ 套接字)

Sending messages from PHP script to multiple Ratchet Websocket apps (via ZMQ Socket)

因此,我正在 运行 设置一个 Ratchet (php) websocket 服务器,该服务器具有连接多个 Ratchet 应用程序 (MessageComponentInterfaces) 的多个路由:

//loop 
$loop   = \React\EventLoop\Factory::create();

//websocket app
$app = new Ratchet\App('ws://www.websocketserver.com', 8080, '0.0.0.0', $loop);

/*
 * load routes
 */
$routeOne = '/example/route';
$routeOneApp = new RouteOneApp();
$app->route($routeOne, $routeOneApp, array('*'));

$routeTwo = '/another/route';
$routeTwoApp = new AnotherApp();
$app->route($routeTwo, $routeTwoApp, array('*'));

从这里我绑定了一个 ZMQ 套接字,以便能够在普通的 apache 服务器上接收从 php 脚本 运行 发送的消息。

// Listen for the web server to make a ZeroMQ push after an ajax request
$context = new \React\ZMQ\Context($loop);
$pull = $context->getSocket(\ZMQ::SOCKET_PULL);
$pull->bind('tcp://127.0.0.1:5050'); // Binding to 127.0.0.1 means the only client that can connect is itself
$pull->on('message', array($routeOneApp, 'onServerMessage'));

服务器终于启动了:

//run
$loop->run();

只要我只将一个棘轮应用程序绑定到 ZMQ 套接字,它就可以正常工作。但是,我希望能够分别将消息推送到两个 Ratchet 应用程序。为此,我想到了将两个 ZMQ 套接字绑定到不同的路由,例如:

$pullOne->bind('tcp://127.0.0.1:5050' . $routeOne); // Binding to 127.0.0.1 means the only client that can connect is itself
$pullOne->on('message', array($routeOneApp, 'onServerMessage'));

$pullTwo->bind('tcp://127.0.0.1:5050' . $routeTwo); // Binding to 127.0.0.1 means the only client that can connect is itself
$pullTwo->on('message', array($routeTwoApp, 'onServerMessage'));

但是,这会导致 ZMQ 在绑定第二个套接字时出现错误消息,指出给定的地址已在使用中。

所以问题是,有没有其他方法可以通过 ZMQ 套接字使用路由? 或者我应该使用其他方法来区分单独的 Ratchet 应用程序的消息,如果是这样,什么是好的解决方案? 我考虑过绑定到 2 个不同的端口,但认为这将是一个非常丑陋的解决方案?!

一般在 TCP 数据包中由 4 元组(发送方 ip、发送方端口、接收方 ip、接收方端口)标识。

当传入数据包到达网络层时,通过查看接收方 ip 和端口将其转发到适当的应用程序。如果您对两个应用程序使用同一对,则该层将无法决定在连接进入时将其发送给谁。

一个解决方案是绑定一个连接并编写一个通用处理程序来查看传入的内容,然后决定(我假设你有一些逻辑)将传入的连接区分到不同的实例,然后调用相应的处理程序。处理程序可以获得连接对象并可以处理连接。

如果您的两个实例是相同的并且谁收到请求并不重要,那么您可以随机将新连接转发给任何处理程序。

编辑:我试图不考虑应用程序类型(Racket/ZMQ 等)来回答问题,因为您要解决的问题是任何网络应用程序都常见的基本问题。

对于这种情况,因为您有两个应用程序 运行 并且想在同一个端口上侦听,您可以有一个通用的处理程序来查看请求 URL 并将连接转发到适当的处理程序。

可以使用

获取请求URL
$querystring = $conn->WebSocket->request->getQuery();

现在客户端可以使用

进行连接
ws://localhost:5050/app1 
and
ws://localhost:5050/app2

您的不同应用现在可以分别处理这些连接。