【问题标题】:How to get public IP of requester in REQ-REP pattern of ZeroMQ?如何在 ZeroMQ 的 REQ-REP 模式中获取请求者的公共 IP?
【发布时间】: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 的人那里获得帮助的地方。

标签: c++ parallel-processing zeromq agent


【解决方案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】:

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

    【讨论】:

      猜你喜欢
      • 2017-02-13
      • 1970-01-01
      • 1970-01-01
      • 2020-07-17
      • 2016-11-17
      • 2014-01-16
      • 2014-01-03
      • 1970-01-01
      • 2013-06-07
      相关资源
      最近更新 更多