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;
}
sorush-r
  • 10,490
  • 17
  • 89
  • 173
  • 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? – raffian May 25 '13 at 00:01
  • 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 :D – sorush-r May 25 '13 at 17:57
  • 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 monitor – raffian May 25 '13 at 18:28
  • @Raffian That's exactly proposed in **Update** yesterday and implemented it today. what I implemented last night :) See the second update – sorush-r May 25 '13 at 19:07
  • 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: http://zguide.zeromq.org/page:all#The-Dynamic-Discovery-Problem – raffian May 25 '13 at 19:23
  • 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. Thanks – sorush-r May 25 '13 at 19:43
  • 3
    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. – kfsone May 27 '13 at 21:23
  • 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? – m01 Jun 02 '13 at 22:36
  • @m01 You're right. What's in home, stays in home :) – sorush-r Jun 06 '13 at 11:01

2 Answers2

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

moodboom
  • 6,225
  • 2
  • 41
  • 45
0

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

thunder
  • 501
  • 4
  • 7