Get TCP address information in ZeroMQ

浪子不回头ぞ 提交于 2020-07-18 10:03:27

问题


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.


回答1:


0MQ doesn't provide the address of peers, for a number of reasons. It's also not that useful since what you really want is the endpoint to receive connections on, not the address the connection was made on.

What I usually do, and it's elegant enough, is pass bind a service to an ephemeral port, get a full connection endpoint ("tcp://ipaddress:port") and send that string in some way, either broadcast to peers, to a central registry, etc. along with my service name. Then, peers who want to connect back can take the service name, look up to find my endpoint, and connect back to me.




回答2:


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.




回答3:


I'm working with version 4.2.1 of the api using the CZMQ binding and I found a solution for my case (ZMQ_STREAM). It works by setting an id before connecting.

The relevant socket option is "ZMQ_CONNECT_RID".

ZMQ api via zmq_setsockopt()

CZMQ api via zsock_set_connect_rid()

Some codes with redacted redacted ips.

const char endpoint1[] = "tcp://1.2.3.4:12345"
const char endpoint2[] = "tcp://5.6.7.8:12345"

zsock_t *stream = zsock_new(ZMQ_STREAM);
zsock_set_connect_rid(stream, endpoint1);
zsock_connect(stream, endpoint1);
zsock_set_connect_rid(stream, endpoint2);
zsock_connect(stream, endpoint2);

Then I get those 2 messages if there is a connection. First frame is the id and second frame is empty on connect/disconnect for ZMQ_STREAM sockets.

[Message1]

[019] tcp://1.2.3.4:12345
[000]

[Message2]

[019] tcp://5.6.7.8:12345
[000] 

Another option is to use the zmq_socket_monitor() or czmq zmonitor. It was one of my first solution but I was looking for something lighter. I was able the get the endpoint that way without setting the id directly on the socket.

The zmonitor zactor make it possible to subscribe to socket events and then it sends a message with 3 frames:

[009] CONNECTED
[002] 14
[021] tcp://127.0.0.1:33445


来源:https://stackoverflow.com/questions/14602442/get-tcp-address-information-in-zeromq

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!