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

sor*_*h-r 11 c++ parallel-processing agent zeromq

听起来在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;
}
Run Code Online (Sandbox Code Playgroud)

moo*_*oom 2

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;
}
Run Code Online (Sandbox Code Playgroud)

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