Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get TCP address information in ZeroMQ

I want to connect clients to a server using ZeroMQ (java bindings, jzmq), but I need the TCP information badly, for example the TCP/IP address of a client request! The problem is, for being able to announce a service in the network I need to grab the TCP address of a request to be able to redirect clients to that service. The broker is a central "service registry" in that case. However, having ZeroMQ services on both sides, I do not see an option to retrieve that information.

What I do now, is to establish a dummy connection using a standard socket to the broker, after the connection is established I grab the IP address used for this connection and close the connection again. The IP address which has been retrieved is now being used for binding on it using a ZeroMQ socket on a random port.

I think this solution is the ugliest solution ever possible, so: What is a better solution to this problem?

Greetings.

like image 498
AlexLiesenfeld Avatar asked Jan 30 '13 11:01

AlexLiesenfeld


2 Answers

In ZMQ 4.x, you may get the string property "Peer-Address" or the "Identity" property. http://api.zeromq.org/4-2:zmq-msg-gets

The Identity is set in the other peer before connect(). http://api.zeromq.org/4-2:zmq-setsockopt#toc20

For example,

const char *identityString = "identity";
zmq::context_t context(1);
zmq::socket_t socket(context, ZMQ_REQ);
socket.setsockopt(ZMQ_IDENTITY, identityString, strlen(identityString));
socket.connect("tcp://127.0.0.1:5555");

Then the other side:

while(1)
{
    zmq::message_t request;
    if (socket.recv(&request, ZMQ_NOBLOCK))
    {
        const char* identity = request.gets("Identity");
        const char* peerAddress = request.gets("Peer-Address");
        printf("Received from %s %s\n", peerAddress, identity);
        break;
    }
}

I'm using CppZmq btw, you should be able to find the relevant calls easily.

like image 111
ZHANG Zikai Avatar answered Sep 17 '22 06:09

ZHANG Zikai


Digging deeper into the libzmq code, I discovered that the library attaches to every message instance the file descriptor that it was received on.

This worked for me

    int sockfd = zmq_msg_get(&msg, ZMQ_SRCFD);

    sockaddr_in addr;
    socklen_t asize = sizeof(addr);
    getpeername(sockfd, (sockaddr*)&addr, &asize);

    std::cout << inet_ntoa(addr.sin_addr) << ":" << addr.sin_port << std::endl;

Note that the FDs can and will be reused by other connections.

like image 25
Akshaye Avatar answered Sep 19 '22 06:09

Akshaye