Sending messages with a PHP script to several Ratchet Websocket applications (via ZMQ Socket)

So, I start the Ratchet web server server (php) with several routes that connect several Ratchet applications (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('*')); 

From here, I bind the ZMQ socket to be able to receive messages sent from php scripts running on a regular Apache server.

 // 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')); 

Finally, the server is running:

 //run $loop->run(); 

This works fine as long as I bind only one ratchet app to the ZMQ socket. However, I would like to be able to separately send messages to both Ratchet applications. For this, I was thinking of binding two ZMQ sockets to different routes, for example:

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

and

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

However, this leads to an error message from ZMQ when binding a second socket, saying that this address is already in use.

So the question is, is there any other way to use routes through a ZMQ socket? Or should I use other means to distinguish between messages for individual Ratchet applications, and if so, what would be a good solution? I was thinking of binding to two different ports, but realized that this would be a pretty ugly solution?

+5
source share
1 answer

In general, TCP packets are identified by four tuples (sender ip, sender port, receiver IP address, receiver port).

When an incoming packet reaches the network layer, it is forwarded to the appropriate application, looking at the receiver's IP address and port. If you use the same pair for both applications, it will be impossible for the layer to decide who to send it to when the connection arrives.

One solution would be to bind one connection and write a regular handler that will look at the incoming content and then decide (suppose you have some kind of logic) to distinguish between incoming connections with different instances, and then call the corresponding handler. A handler can receive a connection object and, therefore, can handle a connection.

If both instances are identical, and it does not matter who receives the request, you can simply accidentally redirect the new connection to any of the handlers.

Edit: I tried to answer the question regardless of the type of application (Racket / ZMQ, etc.), because the problem you are trying to solve is fundamental, common to any network application.

In this case, since you have two applications that are running and want to listen on the same port, you can have a common handler that can look at the request URL and redirect the connection to the corresponding handler.

The request URL can be obtained using

 $querystring = $conn->WebSocket->request->getQuery(); 

Clients can now connect using

 ws://localhost:5050/app1 and ws://localhost:5050/app2 

Now your various applications can handle these connections separately.

+2
source

Source: https://habr.com/ru/post/1263926/


All Articles