ZMQ 通过心跳检测客户端不可用
ZMQ detect client unavailability with heartbeat
我正在使用 zmq,但我无法在文档和示例中找到正确使用以下套接字选项的答案:
- ZMQ_HEARTBEAT_IVL
- ZMQ_HEARTBEAT_TIMEOUT
- ZMQ_HEARTBEAT_TTL
文档指出它们可以与任何套接字类型一起使用(“当使用面向连接的传输时”)。有没有办法将它们与 REQ/REP 套接字对一起使用?
测试客户端代码:
zmq::context_t context( 1 );
zmq::socket_t client( context, ZMQ_REQ );
client.connect( "tcp://localhost:5555" );
// Send request.
std::string request( "test message" );
zmq::message_t message( string.size() );
memcpy( message.data(), string.data(), string.size() );
socket.send( message, flags );
// Wait for reply.
socket.recv( &message );
// Do some work that takes cca 10 secs.
// ...
delete client;
测试服务器代码:
zmq::context_t context( 1 );
zmq::socket_t server( context, zmq::socket_type::rep );
//server.set( zmq::sockopt::rcvtimeo, 5000 );
server.set( zmq::sockopt::heartbeat_ivl, 1000 );
server.set( zmq::sockopt::heartbeat_timeout, 3000 );
server.set( zmq::sockopt::heartbeat_ttl, 3000 );
server.bind( "tcp://*:5555" );
// Wait for request.
zmq::message_t message;
server.recv( &message );
// Send reply.
zmq::message_t message2("Test reply.", 11);
server.send( message);
// Wait for new request.
server.recv( &message );
// ...
我的目标是在客户端完成后结束服务器端。套接字选项 zmq::sockopt::rcvtimeo
工作正常,它关闭服务器端的连接。我认为心跳套接字选项会导致类似的情况,我的意思是在客户端完成其工作后关闭服务器,而不是更早。我在服务器端和客户端尝试了所有可能的组合,但服务器端总是卡在第二个 recv
操作中。
使用 Wireshark 检查本地主机网络流量表明乒乓消息已传递,仅此而已。
所以我的问题是:
- 可以在 REQ/REP 连接中使用这些套接字选项吗?
- 如果是,那又如何呢?哪一方应设置这些套接字选项?
- 如果不是,那么推荐使用哪些套接字类型?
提前致谢!
好的,看来您需要使用 zmq_socket_monitor() 函数。这会导致上下文为自己创建一个 ZMQ_PAIR 套接字,它将绑定到您指定的端点。您必须创建自己的 ZMQ_PAIR 套接字,并将其连接到该端点。
您可以从 ZMQ_PAIR 套接字读取事件消息(请参阅 api 参考以了解这些消息的格式)。因此,您可以在对 zmq_poll() 的调用中包含该 PAIR 套接字,因此当您在 zmq_socket_monitor() 调用中引用的套接字中的状态发生变化时,您的应用程序可以异步通知.
我认为将报告心跳超时的事件是ZMQ_EVENT_DISCONNECTED。
见here。
我想说的是,要从中获得最大价值,您几乎不得不使用 zmq_poll()(或类似方法)。例如,期望接收消息的客户端不能同时在从连接到服务器的套接字调用 zmq_recv() 时被阻塞,也不能在监视器 zmq_recv() 上被阻塞 ZMQ_PAIR套接字。然而,如果您在等待服务器和监视器套接字的 zmq_poll() 调用时被阻塞,那么当有来自服务器的消息或出现问题时,这将 return出现意味着你不会收到消息。
我正在使用 zmq,但我无法在文档和示例中找到正确使用以下套接字选项的答案:
- ZMQ_HEARTBEAT_IVL
- ZMQ_HEARTBEAT_TIMEOUT
- ZMQ_HEARTBEAT_TTL
文档指出它们可以与任何套接字类型一起使用(“当使用面向连接的传输时”)。有没有办法将它们与 REQ/REP 套接字对一起使用?
测试客户端代码:
zmq::context_t context( 1 );
zmq::socket_t client( context, ZMQ_REQ );
client.connect( "tcp://localhost:5555" );
// Send request.
std::string request( "test message" );
zmq::message_t message( string.size() );
memcpy( message.data(), string.data(), string.size() );
socket.send( message, flags );
// Wait for reply.
socket.recv( &message );
// Do some work that takes cca 10 secs.
// ...
delete client;
测试服务器代码:
zmq::context_t context( 1 );
zmq::socket_t server( context, zmq::socket_type::rep );
//server.set( zmq::sockopt::rcvtimeo, 5000 );
server.set( zmq::sockopt::heartbeat_ivl, 1000 );
server.set( zmq::sockopt::heartbeat_timeout, 3000 );
server.set( zmq::sockopt::heartbeat_ttl, 3000 );
server.bind( "tcp://*:5555" );
// Wait for request.
zmq::message_t message;
server.recv( &message );
// Send reply.
zmq::message_t message2("Test reply.", 11);
server.send( message);
// Wait for new request.
server.recv( &message );
// ...
我的目标是在客户端完成后结束服务器端。套接字选项 zmq::sockopt::rcvtimeo
工作正常,它关闭服务器端的连接。我认为心跳套接字选项会导致类似的情况,我的意思是在客户端完成其工作后关闭服务器,而不是更早。我在服务器端和客户端尝试了所有可能的组合,但服务器端总是卡在第二个 recv
操作中。
使用 Wireshark 检查本地主机网络流量表明乒乓消息已传递,仅此而已。
所以我的问题是:
- 可以在 REQ/REP 连接中使用这些套接字选项吗?
- 如果是,那又如何呢?哪一方应设置这些套接字选项?
- 如果不是,那么推荐使用哪些套接字类型?
提前致谢!
好的,看来您需要使用 zmq_socket_monitor() 函数。这会导致上下文为自己创建一个 ZMQ_PAIR 套接字,它将绑定到您指定的端点。您必须创建自己的 ZMQ_PAIR 套接字,并将其连接到该端点。
您可以从 ZMQ_PAIR 套接字读取事件消息(请参阅 api 参考以了解这些消息的格式)。因此,您可以在对 zmq_poll() 的调用中包含该 PAIR 套接字,因此当您在 zmq_socket_monitor() 调用中引用的套接字中的状态发生变化时,您的应用程序可以异步通知.
我认为将报告心跳超时的事件是ZMQ_EVENT_DISCONNECTED。
见here。
我想说的是,要从中获得最大价值,您几乎不得不使用 zmq_poll()(或类似方法)。例如,期望接收消息的客户端不能同时在从连接到服务器的套接字调用 zmq_recv() 时被阻塞,也不能在监视器 zmq_recv() 上被阻塞 ZMQ_PAIR套接字。然而,如果您在等待服务器和监视器套接字的 zmq_poll() 调用时被阻塞,那么当有来自服务器的消息或出现问题时,这将 return出现意味着你不会收到消息。