如何在C++类中重建ZMQ请求套接字实现Lazy Pirate Client
解决ZMQ Lazy Pirate Client模式下套接字重建问题
你的两种尝试都无法正确替换类中的套接字实例,原因如下:
- 第一种方法:在局部作用域创建的
sock变量只是遮蔽了类成员sock,并不会修改类本身的套接字。函数结束后局部变量被销毁,类成员仍为原实例。 - 第二种方法:指针赋值仅改变了指针指向,类成员
sock未被替换,且新分配的套接字会造成内存泄漏。
方案一:利用移动语义替换现有套接字
zmq::socket_t支持移动操作,可通过移动赋值直接替换类成员:
在超时重试的代码块中替换为:
// 关闭现有套接字 sock.close(); // 移动赋值创建新的REQ套接字并重新连接 sock = std::move(zmq::socket_t(context, zmq::socket_type::req)); sock.connect(endp.c_str()); // 更新pollitem的套接字指针(新套接字的文件描述符已变更) items[0].socket = sock;
方案二:使用智能指针管理套接字(更简洁)
将类成员改为std::unique_ptr<zmq::socket_t>,方便重置套接字:
修改类定义:
class request_client_t { private: std::unique_ptr<zmq::socket_t> sock; zmq::context_t& context; public: std::string endp; int retries = 3; int timeout_ms = 1000; request_client_t(zmq::context_t& ctx, std::string target, std::string port) : context(ctx) { endp = "tcp://" + target + ":" + port; sock = std::make_unique<zmq::socket_t>(ctx, zmq::socket_type::req); sock->connect(endp.c_str()); }; ~request_client_t(){ if (sock) sock->close(); }; int send(std::string command, std::string msg, std::vector<std::string>& reply){ zmq::message_t zcommand(command.c_str(),command.size()); zmq::message_t zmsg(msg.c_str(),msg.size()); int retry = retries; zmq_pollitem_t items [] = { { *sock, 0, ZMQ_POLLIN, 0 } }; while(retry){ if(msg != ""){ auto res = sock->send(zcommand, zmq::send_flags::sndmore); res = sock->send(zmsg, zmq::send_flags::none); } else { auto res = sock->send(zcommand, zmq::send_flags::none); } int rc = zmq_poll (items, 1, timeout_ms); if (rc == -1) break; if (items [0].revents & ZMQ_POLLIN) { zmq::message_t zreply; zmq::recv_result_t res = sock->recv(zreply,zmq::recv_flags::none); reply.push_back(zreply.to_string()); while (zreply.more()){ res = sock->recv(zreply,zmq::recv_flags::none); reply.push_back(zreply.to_string()); } return EXIT_SUCCESS; } else if (--retry == 0) { return EXIT_FAILURE; } else { // 重置套接字并重新连接 sock.reset(new zmq::socket_t(context, zmq::socket_type::req)); sock->connect(endp.c_str()); items[0].socket = *sock; } } return EXIT_FAILURE; }; };
注意:使用智能指针后,所有原sock.xxx的调用需改为sock->xxx,同时zmq_pollitem_t的初始化要传入*sock。
内容的提问来源于stack exchange,提问作者Jan
相关产品推荐
相关产品推荐

