我想用 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!
...
编辑:
修改了dealer连接前绑定(bind)路由器的代码,问题依旧:
$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
最佳答案
我终于解决了这个问题。得到@Jason 评论的帮助 没有使用过 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
类中实现,直接调用PHP的ZMQ api中实现的方法,所以我尝试调用sendmulti
将这两个参数包装在一个数组中.它起作用了,所以我尝试调用传递相同数组的第一个 send
方法,我不知道为什么但它也起作用了,所以诀窍是调用:$router->send(array('A', \ZMQ::MODE_SNDMORE));
$router->send(array('END'));
代替:
$router->send('A', \ZMQ::MODE_SNDMORE);
$router->send('END');
另外,请注意位于 GitHub 存储库中的 ZMQ PHP API,这是错误的。 PhpStorm 以某种方式下载了位于某处似乎正确的另一个 ZMQ PHP API,该 API 中的
sendmulti
方法原型(prototype)如下所示:public function sendmulti(array $message, $mode = 0)
令人惊讶的是,对该方法的以下调用似乎给出了相同的结果:
$router->send(array('A', \ZMQ::MODE_SNDMORE));
$router->send(array('A'), \ZMQ::MODE_SNDMORE);
关于php - react ZMQ,路由器到经销商,不工作。 ZMQ 4.0.5,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30469459/