[英]How can I clean up properly when recv is blocking?
考虑下面的示例代码(我快速输入它作为示例,如果有错误则无关紧要 - 我对理论感兴趣)。
bool shutDown = false; //global
int main()
{
CreateThread(NULL, 0, &MessengerLoop, NULL, 0, NULL);
//do other programmy stuff...
}
DWORD WINAPI MessengerLoop( LPVOID lpParam )
{
zmq::context_t context(1);
zmq::socket_t socket (context, ZMQ_SUB);
socket.connect("tcp://localhost:5556");
socket.setsockopt(ZMQ_SUBSCRIBE, "10001 ", 6);
while(!shutDown)
{
zmq_msg_t getMessage;
zmq_msg_init(&getMessage);
zmq_msg_recv (&getMessage, socket, 0); //This line will wait forever for a message
processMessage(getMessage);
}
}
创建一个线程以等待传入消息并适当地处理它们。 线程正在循环,直到shutDown
设置为true。
在ZeroMQ中, 指南明确说明了必须清理的内容,即消息,套接字和上下文。
我的问题是:由于recv
将永远等待消息,阻塞线程,如果从未收到消息,如何安全地关闭此线程?
阻塞调用将以几种方式退出。 首先,这取决于您的语言和绑定,中断(Ctrl-C,SIGINT,SIGTERM)将退出调用。 您将返回(再次,取决于您的绑定)错误或空消息(libzmq返回EINTR错误)。
其次,如果在另一个线程中终止上下文,阻塞调用也将退出(libzmq返回ETERM错误)。
第三,您可以在套接字上设置超时,以便在没有数据的情况下,在任何情况下都会在超时后返回。 我们不经常这样做,但在某些情况下它可能很有用。
最后,我们在实践中做的是永远不会阻塞接收但是使用zmq_poll找出套接字有消息等待的时间,然后从这些套接字接收。 这是扩展到处理更多套接字的方法。
您可以使用非阻塞调用标志ZMQ_DONTWAIT
while(!shutDown)
{
zmq_msg_t getMessage;
zmq_msg_init(&getMessage);
while(-1 == zmq_msg_recv(&getMessage, socket, ZMQ_DONTWAIT))
{
if (EAGAIN != errno || shutDown)
{
break;
}
Sleep(100);
}
processMessage(getMessage);
}
每当zmq上下文被破坏时,zmq_msg_recv将收到-1。 我在我的所有代码中使用它作为终止条件。
while (!shutdown)
{
..
..
int rc = zmq_msg_recv (&getMessage, socket, 0);
if (rc != -1)
{
processMessage;
}
else
break;
}
请记住在main()的末尾销毁zmq上下文以进行适当的清理。
zmq_ctx_destroy(zctx);
假设您有一个类说SUB(订阅者)管理您的ZMQ消息的接收。 在main函数/类的析构函数或exit函数中,调用以下函数:
pub->close();
///
/// Close the publish context
///
void PUB::close()
{
zmq_close (socket);
zmq_ctx_destroy (context);
}
这将使'recv'阻塞终止,并显示您可以忽略的错误消息。 应用程序将以正确的方式舒适地退出。 这是正确的方法。 祝好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.