ZMQ: Poll returns socket once

I love ZeroMQ. However in the beginning it is really hard to wrap you mind around some of the concepts.

One of the things that should be clear to you before you start using ZMQ is how polling works. In order to understand it you might want to run the following example scripts.

write.php

<?php
$context = new ZMQContext();
$socket1 = $context->getSocket(ZMQ::SOCKET_PUSH);
$socket1->connect('ipc://socket1.ipc');

// Send 5 messages.
$socket1->send('socket1 message1');
$socket1->send('socket1 message2');
$socket1->send('socket1 message3');
$socket1->send('socket1 message4');

echo 'Waiting for sockets to close (LINGER)...'.PHP_EOL;

read.php

<?php
$context = new ZMQContext();
$socket1 = $context->getSocket(ZMQ::SOCKET_PULL);
$socket1->bind('ipc://socket1.ipc');

$poll = new ZMQPoll();
$poll->add($socket1, ZMQ::POLL_IN);

$read = $write = array();

// Read "ALL" the sockets, just one for now...
$events = $poll->poll($read, $write, 200);
foreach ($read as $sock) {
        echo $sock->recv().PHP_EOL;
}

echo 'Events: '.$events.PHP_EOL;
echo 'Readable: '.count($read).PHP_EOL;

Some might expect “Events” to be 5 and some event expect $read to contain an array with 5 times the instance of $socket1.

However this is what happens when you run the code:

reen@server$ php write.php &
[1] 15560
Waiting for sockets to close (LINGER)...

reen@server$ php read.php
socket1 message1
Events: 1
Readable: 1
[1]+  Done                    php write.php

The messages are send instantly and the write script is only active because of the lingering. When you run read you will receive only 1 message, but there should already be 5 in the queue.

This is because poll claims 1 message at every socket if available and poll returns the sockets that where able to give one. So in order to receive all the messages, you should continue polling until it returns 0 events.

readall.php

<?php
$context = new ZMQContext();
$socket1 = $context->getSocket(ZMQ::SOCKET_PULL);
$socket1->bind('ipc://socket1.ipc');

$poll = new ZMQPoll();
$poll->add($socket1, ZMQ::POLL_IN);

$read = $write = array();
while (true) {
        $events = $poll->poll($read, $write, 200);
        if ($events <= 0) {
                break;
        }
        foreach ($read as $sock) {
                echo $sock->recv().PHP_EOL;
        }
}

echo 'Events: '.$events.PHP_EOL;
echo 'Readable: '.count($read).PHP_EOL;

Side note
After running read the queue is cleared. This is quite logic, because it crashes right after receiving 1 message, losing all the data that was transferred to the read script by ZMQ internally.