在我的一个应用程序中,我正在使用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 Studio2015。如何清洁关闭DEALER/ROUTER连接?这是libzmq中的错误吗?

最佳答案

在您的系统中使用ZMQ_DONTWAIT是否可行

调用并评估错误代码?
将您的代码更改为

// 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));
会导致

或者,可以使用socket monitor来检测关闭事件并阻止进一步发送吗?这确实取决于您的体系结构。

10-04 12:26