如何干净地关闭 zeromq DEALER/ROUTER inproc 连接
How do I cleanly shutdown zeromq DEALER/ROUTER inproc connections
在我的一个应用程序中,我使用了 DEALER/ROUTER inproc 连接。我将 DEALER 套接字上的 linger 选项设置为 0,这样一旦 ROUTER 套接字关闭,所有在 DEALER 套接字上发送的消息都将被丢弃。虽然这对 TCP 连接很有效,但它会阻塞 inproc。这是一个最小的工作示例:
#include <zmq.h>
#include <windows.h>
int main()
{
void *context = zmq_ctx_new();
void *router = zmq_socket(context, ZMQ_ROUTER);
zmq_bind(router, "inproc://socket");
void *dealer = zmq_socket(context, ZMQ_DEALER);
zmq_connect(dealer, "inproc://socket");
int linger = 0;
zmq_setsockopt(dealer, ZMQ_LINGER, &linger, sizeof(linger));
zmq_close(router);
// sleep for 1 ms
Sleep(1);
// this call blocks
zmq_send(dealer, "message", 7, 0);
zmq_close(dealer);
zmq_ctx_destroy(context);
return 0;
}
在 DEALER 套接字可以关闭之前,zmq_send() 调用阻塞。在这个最小的示例中,我必须添加一个 Sleep(1) 调用。省略此调用时,zmq_send() 不会阻塞。阻塞时调用栈如下:
[External Code]
libzmq.dll!zmq::signaler_t::wait(int timeout_) Line 253 C++
libzmq.dll!zmq::mailbox_t::recv(zmq::command_t * cmd_, int timeout_) Line 80 C++
libzmq.dll!zmq::socket_base_t::process_commands(int timeout_, bool throttle_) Line 1023 C++
libzmq.dll!zmq::socket_base_t::send(zmq::msg_t * msg_, int flags_) Line 869 C++
libzmq.dll!s_sendmsg(zmq::socket_base_t * s_, zmq_msg_t * msg_, int flags_) Line 346 C++
libzmq.dll!zmq_send(void * s_, const void * buf_, unsigned __int64 len_, int flags_) Line 371 C++
我正在使用 Windows 10 x64、libzmq 4.2.1(也用 4.1.6 对其进行了测试)和 Visual Studio 2015。我怎样才能彻底关闭 DEALER/ROUTER连接?这是 libzmq 中的错误吗?
在您的
中使用ZMQ_DONTWAIT是否可行
zmq_send()
调用并评估错误代码?
将代码更改为
// this call blocks no more
zmq_send(dealer, "message", 7, ZMQ_DONTWAIT);
int ec = zmq_errno();
printf("code: %d\nstring: %s\n", ec, zmq_strerror(ec));
会导致
code: 11
string: Resource temporarily unavailable
或者,是否可以使用 socket monitor 来检测关闭事件并防止进一步发送?这确实取决于您的体系结构。
在我的一个应用程序中,我使用了 DEALER/ROUTER inproc 连接。我将 DEALER 套接字上的 linger 选项设置为 0,这样一旦 ROUTER 套接字关闭,所有在 DEALER 套接字上发送的消息都将被丢弃。虽然这对 TCP 连接很有效,但它会阻塞 inproc。这是一个最小的工作示例:
#include <zmq.h>
#include <windows.h>
int main()
{
void *context = zmq_ctx_new();
void *router = zmq_socket(context, ZMQ_ROUTER);
zmq_bind(router, "inproc://socket");
void *dealer = zmq_socket(context, ZMQ_DEALER);
zmq_connect(dealer, "inproc://socket");
int linger = 0;
zmq_setsockopt(dealer, ZMQ_LINGER, &linger, sizeof(linger));
zmq_close(router);
// sleep for 1 ms
Sleep(1);
// this call blocks
zmq_send(dealer, "message", 7, 0);
zmq_close(dealer);
zmq_ctx_destroy(context);
return 0;
}
在 DEALER 套接字可以关闭之前,zmq_send() 调用阻塞。在这个最小的示例中,我必须添加一个 Sleep(1) 调用。省略此调用时,zmq_send() 不会阻塞。阻塞时调用栈如下:
[External Code]
libzmq.dll!zmq::signaler_t::wait(int timeout_) Line 253 C++
libzmq.dll!zmq::mailbox_t::recv(zmq::command_t * cmd_, int timeout_) Line 80 C++
libzmq.dll!zmq::socket_base_t::process_commands(int timeout_, bool throttle_) Line 1023 C++
libzmq.dll!zmq::socket_base_t::send(zmq::msg_t * msg_, int flags_) Line 869 C++
libzmq.dll!s_sendmsg(zmq::socket_base_t * s_, zmq_msg_t * msg_, int flags_) Line 346 C++
libzmq.dll!zmq_send(void * s_, const void * buf_, unsigned __int64 len_, int flags_) Line 371 C++
我正在使用 Windows 10 x64、libzmq 4.2.1(也用 4.1.6 对其进行了测试)和 Visual Studio 2015。我怎样才能彻底关闭 DEALER/ROUTER连接?这是 libzmq 中的错误吗?
在您的
中使用ZMQ_DONTWAIT是否可行zmq_send()
调用并评估错误代码?
将代码更改为
// this call blocks no more
zmq_send(dealer, "message", 7, ZMQ_DONTWAIT);
int ec = zmq_errno();
printf("code: %d\nstring: %s\n", ec, zmq_strerror(ec));
会导致
code: 11
string: Resource temporarily unavailable
或者,是否可以使用 socket monitor 来检测关闭事件并防止进一步发送?这确实取决于您的体系结构。