Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get public IP of requester in REQ-REP pattern of ZeroMQ?

Sounds like it makes no sense in ZeroMQ to work with sockets in terms of traditional UNIX sockets. I designed an architecture for a distributed search algorithm based on a wrong perception of ZeroMQ. In my program, there is an agent responsible of monitoring other agents and collect their data. Real data will be transferred between agents following PULL-PUSH or PUB-SUB pattern. Each agent have a PULL socket listening on for incoming messages. Each messages includes an ID number which specifies the sender identification.

At initialization stage, monitor is supposed to listen on its REP socket. Each agent will connect to monitor's well-known REP socket and introduce itself (sends his ID number and the port number the agent is listening on). The monitor stores all data about agents in a records of three fields: <ID, IP, port>. (This is where I have problem with ZMQ.) When certain count of agents become ready, the monitor sends all data (each agent's <IP,ID,port>) to all agents. The last step is done by a PUB-SUB pattern between agents and monitor.

This image may help to get an idea what I meant to implement: De-centralized Search

In above picture, the monitor should send it's table to everybody. The key question is how to get public IP address of a requester (any agent) in a REQ-REP pattern? All agents bind to their local host (127.0.0.1). They're supposed to be distributed on arbitrary number of host. So AFAIK they need to know public IP of each other.

In the case that no solution exists, any help on redesigning architecture is appropriate.

Update

A candidate solution I can think of, is to modify each agent to bind to his/her public IP instead of localhost. If there is a magic way of getting public IP address, any agent can send his address to the monitor.

Second Update

Currently the agent obtains its public IP address and sends it via message to server:

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;
}
like image 518
sorush-r Avatar asked May 24 '13 14:05

sorush-r


1 Answers

boost can determine your IP address in a portable manner as follows:

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;
}

But that doesn't mean it's an easy fix - what if the box has multiple IPs/NICs/WAN/LAN etc.... When I had a similar situation recently, I forced the caller to explicitly provide the desired IP and port on the command line, then shared it when connecting to other processes on other hosts (in my case, via HTTP).

like image 125
moodboom Avatar answered Nov 15 '22 13:11

moodboom