如何在 ZeroMQ 的 REQ-REP 模式中获取请求者的公共 IP?

Posted

技术标签:

【中文标题】如何在 ZeroMQ 的 REQ-REP 模式中获取请求者的公共 IP?【英文标题】:How to get public IP of requester in REQ-REP pattern of ZeroMQ? 【发布时间】:2013-05-20 05:12:19 【问题描述】:

听起来在 ZeroMQ 中按照传统的 UNIX 套接字使用套接字是没有意义的。我基于对 ZeroMQ 的错误认知,为分布式搜索算法设计了一个架构。在我的程序中,有一个代理负责监控其他代理并收集他们的数据。真实数据将按照 PULL-PUSH 或 PUB-SUB 模式在代理之间传输。每个代理都有一个 PULL 套接字侦听传入消息。每条消息都包含一个 ID 号,用于指定发件人的身份。

在初始化阶段,监视器应该监听它的 REP 套接字。每个代理将连接到监视器众所周知的 REP 套接字并自我介绍(发送他的 ID 号和代理正在侦听的端口号)。监视器将有关代理的所有数据存储在三个字段的记录中:<ID, IP, port>。 (这就是我对 ZMQ 有问题的地方。)当一定数量的代理准备好时,监视器将所有数据(每个代理的 <IP,ID,port>)发送给所有代理。最后一步由代理和监视器之间的 PUB-SUB 模式完成。

这张图片可能有助于了解我想要实现的内容:

在上图中,监视器应该将它的表发送给每个人。关键问题是如何在 REQ-REP 模式中获取请求者(任何代理)的公共 IP 地址?所有代理都绑定到其本地主机 (127.0.0.1)。它们应该分布在任意数量的主机上。所以AFAIK他们需要知道彼此的公共IP。

在不存在解决方案的情况下,重新设计架构的任何帮助都是适当的。

更新

我能想到的一个候选解决方案是修改每个代理以绑定到他/她的公共 IP 而不是localhost。如果有一种获取公共 IP 地址的神奇方法,任何代理都可以将他的地址发送到监视器。

第二次更新

目前代理获取了自己的公网IP地址,并通过消息发送给服务器:

std::string AIT::ABT_Socket::getIP() 
    std::string address = "";
    FILE * fp = popen("ifconfig", "r");
    if (fp) 
        char *p = NULL, *e;
        size_t n;
        while ((getline(&p, &n, fp) > 0) && p) 
            if (p = strstr(p, "inet addr:")) 
                p += 10;
                if (e = strchr(p, ' ')) 
                    *e = '\0';
                    return std::string(p);
                    address = std::string(p);

                
            
        
    
    pclose(fp);
    return address;

【问题讨论】:

澄清一下,您是说监视器需要知道代理的 IP 地址才能将其表发送给他们? 没有。监视器需要知道代理的 IP 地址,才能将这些 IP 地址发送给所有代理。换句话说,构建表。它可以发送消息,但它不知道使用 ZeroMQ 的 IP 地址:D 能否将每个代理的 IP 地址存储在配置文件中,或者只使用ifconfig 并解析出inet address 来获取IP?然后每个代理可以在消息中将 IP 发送给监视器 @Raffian 这正是昨天在更新中提出的,并在今天实施。我昨晚实施的 :) 查看第二次更新 ZMQ 是独立于传输的,这就是为什么你无法找到某人的地址(可能不止一个地址)。如果您绝对必须让代理进行任意直接连接,那么您需要让他们将其地址作为元协议的一部分提交给监视器 - 还有一种方法可以将信息与给定的会话/连接相关联。我建议您加入 ZeroMQ 邮件列表并在那里提出问题,这是您最有可能从完全熟悉 ZMQ 的人那里获得帮助的地方。 【参考方案1】:

boost 可以通过以下便携式方式确定您的 IP 地址:

tcp::resolver resolver(io_service);
tcp::resolver::query query(boost::asio::ip::host_name(), "");
tcp::resolver::iterator iter = resolver.resolve(query);
tcp::resolver::iterator end; // End marker.
while (iter != end)

    tcp::endpoint ep = *iter++;
    std::cout << ep << std::endl;

但这并不意味着它很容易解决 - 如果盒子有多个 IP/NIC/WAN/LAN 等怎么办......当我最近遇到类似情况时,我强迫调用者明确提供所需的 IP和命令行上的端口,然后在连接到其他主机上的其他进程时共享它(在我的情况下,通过 HTTP)。

【讨论】:

【参考方案2】:

您为什么不直接将其作为有效负载的一部分发送?

【讨论】:

以上是关于如何在 ZeroMQ 的 REQ-REP 模式中获取请求者的公共 IP?的主要内容,如果未能解决你的问题,请参考以下文章

ZMQ通信模式:REQ-REP模式

为啥套接字连接的基本抽象并不常见?

ZMQ源码分析--ROUTER-DEALER & REQ-REP

ZeroMQ/ZMQ 推/拉模式的用处

grpc 和 zeromq 比较

ZeroMQ:如何实现客户端通知?