如何在 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?的主要内容,如果未能解决你的问题,请参考以下文章