繁体   English   中英

关闭ZeroMQ订户的正确方法是什么?

[英]What is the proper way to shutdown a ZeroMQ Subscriber?

我在ROS内的ZeroMQ中使用PUB/SUB模型。

只需在终端中按Ctrl + C即可停止SUB -subscriber。

但是,每当我实际按下Ctrl + C时 ,它会因抛出以下错误而停止:

^Cterminate called after throwing an instance of 'zmq::error_t'
  what():  Interrupted system call
Aborted (core dumped)

以下是代码段:

#include <ros/ros.h>
#include <zmq.hpp>

int main(int argc, char **argv)
{
  ros::init(argc, argv, "node_name", ros::init_options::AnonymousName);
  ros::NodeHandle nh;
  ros::Publisher pub;

  //  Prepare context and publisher
  zmq::context_t zmq_context(1);
  zmq::socket_t zmq_socket(zmq_context, ZMQ_SUB);
  zmq_socket.connect("tcp://192.168.1.20:9001");

  std::string TOPIC = "";
  zmq_socket.setsockopt(ZMQ_SUBSCRIBE, TOPIC.c_str(), TOPIC.length()); // allow all messages

  int timeout = 1000;  // Timeout to get out of the while loop since recv is blocking
  zmq_socket.setsockopt(ZMQ_RCVTIMEO, &timeout, sizeof(timeout));

  while (ros::ok())
  {
      zmq::message_t msg;
      int rc = zmq_socket.recv(&msg);
      if (rc)
      {
          //receive data and prepare it for publishing
          pub.publish(data);
          ros::spinOnce();
      }
  }

  // Clean up the socket and context here
  zmq_socket.close();
  zmq_context.close();

  return 0;
}

如何避免错误以便正确关闭用户?

如果没有关于Ctrl + C如何被捕获和处理的细节,我总是会添加(C ++绑定细节可能与版本不同):

int main(int argc, char **argv)
{
    zmq_socket.connect(    "tcp://192.168.1.20:9001" );
    zmq_socket.setsockopt( ZMQ_LINGER, 0 );              // ALWAYS
    ...

    while( ROS::ok() )
    {
       ...
    }
    std::cout << "SIG:: will .close() after ROS::ok()-loop exit" << std::flush;
    zmq_socket.close();

    std::cout << "SIG:: will .term()  after a Socket()-instance .close()'d" << std::flush;
    zmq_context.close();

    std::cout << "SIG:: will return 0 after a Context()-instance .term()'d" << std::flush;
    return 0;
}

我意识到问题是由int rc = zmq_socket.recv(&msg)引起的,因此我做了以下改进 -

  1. 我用trycatch
  2. 设置ZMQ_LINGER通过@ user3666197的建议

以下是代码段 -

int linger = 0; // Proper shutdown ZeroMQ
zmq_socket.setsockopt(ZMQ_LINGER, &linger, sizeof(linger));

std::string socket_address = "tcp://192.168.1.20:9001";
zmq_socket.connect(socket_address.c_str());

ros::Duration duration(0.1); // in seconds (100 ms)
while (ros::ok())
{
    zmq::message_t msg;
    int rc = 0;
    try
    {
        rc = zmq_socket.recv(&msg);
    }
    catch (zmq::error_t& e)
    {
        ROS_DEBUG_STREAM("ZMQ Error. " << e.what());
    }
    if (rc)
    {
        unsigned char* byte_ptr = static_cast<unsigned char*>(msg.data());
        const int msg_length = msg.size();
        // receive data and prepare it for publishing
        pub.publish(data);
        ros::spinOnce();
    }
    else
    {
        ROS_DEBUG_STREAM("Pointcloud recv() returned 0");
        duration.sleep();
    }
}

谢谢

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM