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

2

11

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;
}
Extension answered 24/5, 2013 at 14:44 Comment(9)
Just to clarify, you're saying the monitor needs to know the IP address of the agents so it can send to them its table?Condominium
No. The monitor needs to know he IP address of the agents, to send those IP addresses to all of them. In other word, to construct the table. It can send messages, but it's not aware of IP address using ZeroMQ :DExtension
Can you store the IP address on each agent in a config file, or just use ifconfig and parse out inet address to get the IP? Then each agent can send the IP in a message to the monitorCondominium
@Raffian That's exactly proposed in Update yesterday and implemented it today. what I implemented last night :) See the second updateExtension
I see. If agents need to communicate, why not use N-to-N pub/sub model and use a ZMQ proxy in the middle? The agents connect to the proxy on well-known address, the proxy binds to the same well-known address, and the agents can publish and receive data from each other that way, they don't need to know IP address of each other, unless you must know the IP for another reason. just an idea. See this: zguide.zeromq.org/page:all#The-Dynamic-Discovery-ProblemCondominium
I'm new with ZeroMQ. Agents may want to send information to a subset of all other agents they know about. I will check that link. ThanksExtension
ZMQ is transport-independent, that's why you can't find out someone's address (it could be more than one address). If you absolutely have to have agents making arbitrary direct connections, then you will need to have them submit their address to the monitor as part of your meta-protocol - there's also a way to associate information with a given session/connection. I would suggest you join the ZeroMQ mailing list and ask the question there, that's where you are most likely to find help from people thoroughly familiar with ZMQ.Wideeyed
Perhaps I'm missing something, but if you bind to 127.0.0.1, nothing else (e.g. a program running on another host, say 10.10.10.3) can connect to your listening socket, right?Husbandman
@Husbandman You're right. What's in home, stays in home :)Extension
P
2

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).

Pullover answered 26/7, 2013 at 14:35 Comment(0)
R
0

Why don't you just send it through as part of the payload?

Rash answered 11/7, 2016 at 17:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.