You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 23:30:58