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

时间:2017-02-07 17:10:08

标签: php zeromq ratchet phpwebsocket

所以,我正在运行一个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应用程序的消息,如果是,那么什么是一个好的解决方案? 我想过绑定到两个不同的端口,但想到这将是一个非常难看的解决方案?!

1 个答案:

答案 0 :(得分:2)

通常,TCP数据包由4元组(发送方IP,发送方端口,接收方IP,接收方端口)标识。

当传入数据包到达网络层时,通过查看接收方IP和端口将其转发到相应的应用程序。如果您为这两个应用程序使用相同的对,那么当连接进入时,图层将无法决定将其发送给谁。

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

如果您的实例都是相同的,并且获取请求的人无关紧要,那么您可以随意将新连接转发给任何处理程序。

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

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

可以使用

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

现在客户端可以使用

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

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