Реагировать на ZMQ, Маршрутизатор к Дилеру, не работает. ZMQ 4.0.5

Я хочу создать асинхронный маршрутизатор для обмена сообщениями с React, но он не работает. Код в http://zguide.zeromq.org/php:rtdealer работает, но я не могу определить, что я делаю по-другому. Я использую libzmq 4.0.5

Вот мой код:

$context = new React\ZMQ\Context($loop);

$worker = $context->getSocket(\ZMQ::SOCKET_DEALER);
$worker->setSockOpt(\ZMQ::SOCKOPT_IDENTITY, 'A');
$worker->connect('tcp://127.0.0.1:5556');
$worker->send('END');

$worker->on('error', function ($e) {
var_dump($e->getMessage());
});

$worker->on('messages', function($msg) use ($worker) {
echo 'Dealer messages'. PHP_EOL;
var_dump($msg);
});

$worker->on('message', function($msg) use ($worker) {
echo 'Dealer message'. PHP_EOL;
var_dump($msg);
});

$router = $context->getSocket(\ZMQ::SOCKET_ROUTER);
$router->bind('tcp://127.0.0.1:5556');

$i = 0;
$loop->addPeriodicTimer(1, function (React\EventLoop\Timer\Timer $timer) use (&$i, $router) {
echo 'Time to send!'. PHP_EOL;
$i++;
$router->send('A', \ZMQ::MODE_SNDMORE);
$router->send('END');
});

$router->on('messages', function($msg) use ($router) {
echo 'Router messages'. PHP_EOL;
var_dump($msg);
});

$router->on('message', function($msg) {
echo 'Router message'. PHP_EOL;
var_dump($msg);
});

$loop->run();

Проблема в том, что только дилер отправляет первое сообщение «END». После этого маршрутизатор пытается отправить сообщения, но дилер не получает их.

Кроме того, эта функция, кажется, вызывается только один раз:

// \React\ZMQ\SocketWrapper
public function handleReadEvent()
{
$messages = $this->socket->recvmulti(ZMQ::MODE_NOBLOCK);
echo 'Receiving...';    // Added
var_dump($messages);    // Added

if ($messages !== false) {
if (count($messages) === 1) {
$this->emit('message', array($messages[0]));
}

$this->emit('messages', array($messages));
}
}

Выход:

Receiving...array(2) {
[0]=>
string(1) "A"[1]=>
string(3) "END"}
Router messages
array(2) {
[0]=>
string(1) "A"[1]=>
string(3) "END"}
Time to send!
Time to send!
Time to send!
Time to send!
Time to send!
...

Редактировать:

Изменен код для привязки роутера до того, как дилер подключится к нему, проблема все еще происходит:

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

$context = new React\ZMQ\Context($loop);

$router = $context->getSocket(\ZMQ::SOCKET_ROUTER);
$router->bind('tcp://127.0.0.1:5556');

$loop->addPeriodicTimer(10, function (React\EventLoop\Timer\Timer $timer) use ($router) {
echo 'Router sending messages with an interval of 10 seconds'. PHP_EOL;
$router->send('A', \ZMQ::MODE_SNDMORE);
$router->send('END');
});

$router->on('messages', function($msg) use ($router) {
echo 'Router messages'. PHP_EOL;
var_dump($msg);
});

$router->on('message', function($msg) {
echo 'Router message'. PHP_EOL;
var_dump($msg);
});

$worker = $context->getSocket(\ZMQ::SOCKET_DEALER);

$loop->addPeriodicTimer(5, function (React\EventLoop\Timer\Timer $timer) use ($worker) {
echo 'After 5 seconds from router binding, connect the dealer and send something'. PHP_EOL;
$worker->setSockOpt(\ZMQ::SOCKOPT_IDENTITY, 'A');
$worker->connect('tcp://127.0.0.1:5556');
$worker->send('END');
$timer->getLoop()->cancelTimer($timer);     // Cancel the timer after connecting
});

$worker->on('error', function ($e) {
var_dump($e->getMessage());
});

$worker->on('messages', function($msg) use ($worker) {
echo 'Dealer messages'. PHP_EOL;
var_dump($msg);
});

$worker->on('message', function($msg) use ($worker) {
echo 'Dealer message'. PHP_EOL;
var_dump($msg);
});

$loop->run();

Это вывод терминала:

After 5 seconds from router binding, connect the dealer and send something
Receiving...array(2) {
[0]=>
string(1) "A"[1]=>
string(3) "END"}
Router messages
array(2) {
[0]=>
string(1) "A"[1]=>
string(3) "END"}
Router sending messages with an interval of 10 seconds
Router sending messages with an interval of 10 seconds
Router sending messages with an interval of 10 seconds
Router sending messages with an interval of 10 seconds
Router sending messages with an interval of 10 seconds
Router sending messages with an interval of 10 seconds
Router sending messages with an interval of 10 seconds
Router sending messages with an interval of 10 seconds

3

Решение

Я наконец-то решил проблему. Помогло @ комментарий Джейсона Не используя PHP / React, вы уверены, что ваше пространство имен правильное? , Я посмотрел на sendметод называется. Этот метод выглядит так:

// \React\ZMQ\SocketWrapper

public function send($message)
{
echo 'Inside send, sending message'. PHP_EOL; //This line was added by myself
$this->buffer->send($message);
}

Тогда я подумал: хорошо, если я вызываю этот метод так:

$router->send('A', \ZMQ::MODE_SNDMORE);

Второй аргумент никогда не передается.

Затем я увидел, что sendmultiметод не был реализован в SocketWrapperи __callметод был реализован в этом SocketWrapper класс, чтобы вызвать напрямую метод, реализованный в API ZMQ для PHP, поэтому я попытался вызвать sendmultiоборачивая эти два параметра в массив. Сработало, поэтому я попытался позвонить первым sendметод, передающий тот же массив, и я не знаю почему, но это тоже сработало, поэтому трюк вызывал:

$router->send(array('A', \ZMQ::MODE_SNDMORE));
$router->send(array('END'));

Вместо:

$router->send('A', \ZMQ::MODE_SNDMORE);
$router->send('END');

Также будьте осторожны с PHP API ZMQ, расположенным в репозитории GitHub, это неправильно. PhpStorm каким-то образом загрузил другой PHP API ZMQ, расположенный где-то, что кажется правильным, sendmultiПрототип метода выглядит следующим образом в этом API:

public function sendmulti(array $message, $mode = 0)

Удивительно, но следующие вызовы этого метода, похоже, дают те же результаты:

$router->send(array('A', \ZMQ::MODE_SNDMORE));
$router->send(array('A'), \ZMQ::MODE_SNDMORE);
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]