I’m testing ZeroMQ for PHP. My goal is to send messages to a Python script.
Everything works fine if i launch my transmission script from PHP cli
php /path/to/myscript.php
while it fails if it’s a web request. I’ve tried executing the server script from PHP cli as above (which seems to be the more logical way) and with a web request.
I’ve got a Centos 7 server with PHP 7.2 and ZeroMQ 1.1.3 installed through PECL install.
I even tried launching the above command with shell_exec/exec inside the client script but it doesn’t work. Connection works fine, but it doesn’t send nor receive.
Client code:
$context = new ZMQContext();
// Socket to talk to server
echo "Connecting to hello world server...n";
$requester = new ZMQSocket($context, ZMQ::SOCKET_REQ);
$currentObject = $requester->connect("tcp://localhost:5555");
for ($request_nbr = 0; $request_nbr != 10; $request_nbr++) {
printf ("Sending request %d...n", $request_nbr);
$risSend = $requester->send("Hello", ZMQ::MODE_NOBLOCK);
print_r($risSend);
$reply = $requester->recv();
printf ("Received reply %d: [%s]n", $request_nbr, $reply);
}
Server Code:
$context = new ZMQContext(1);
// Socket to talk to clients
$responder = new ZMQSocket($context, ZMQ::SOCKET_REP);
$responder->bind("tcp://*:5555");
while (true) {
// Wait for next request from client
$request = $responder->recv();
printf ("Received request: [%s]n", $request);
// Send reply back to client
$responder->send("World");
}
The browser gets stuck, without any error. Even using a timeout it reaches the limit and exits but I can’t get any error message.
2
Answers
Ok, i finally found the solution. Thanks to @user3666197 i managed to get an error. And it was a "permission denied" error.
With CentOS (and probably all linux sytems with SELinux) you gotta add a rule for the port used by ZMQ for the webserver.
Example:
This is pretty legal state. For it to happen, it is quite enough to “miss” the arrival of the first
REQ
-side-already dispatched request and due to a pleasure do depend on a distributed-Finite-State-Automaton, we fall into an unsalvageable dead-lock, where theREQ
-side waits for an answer, that will never arrive (see next) and theREP
-side waits for a request, that will never arrive (see theREQ
-side already waiting ) and such a state remains forever that.A best next step:
In case one has never worked with ZeroMQ,
or have never met the concept of the art of Zen-of-Zero,
one may here enjoy to first look at “ZeroMQ Principles in less than Five Seconds“ before diving into further details
Start
with unconditionally working archetypes – a pair of
PUSH / PULL
simplex-channels, that do not require a dFSA-two-step ofREQ-REP-REQ-REP-REQ-REP-...-{deadlock}
… a principally unavoidable terminal state, about which one is just never sure when it happens, but it will … at some later time :o)Next,
may increase a robustness of the message-flow, using
zmq_setsockopt( ZMQ_IMMEDIATE, 1 )
that avoids moving messages onto incomplete connections between / among peers.Always
prefer non-blocking forms of
.recv()
-methods, best with a pre-test of a message-presence with a.poll()
-method.Poller
-class, while available in many language-bindings is not always as handy and as flexible as using explicit.poll()
-method directly on aSocket
-instance.Also feel free to read more about fine-tuning the ZeroMQ tools and other implications of the Art of the Zen-of-Zero here.
A Server-side mock-up: As a { PASS | FAIL }-proof of
.send()---.recv()
-delivery chain works?Client-side mock-up, to test the PUSH-er lives and
.send()
-s