Получить информацию об адресе TCP в ZeroMQ

Я хочу подключить клиентов к серверу с помощью ZeroMQ (привязки java, jzmq), но мне очень нужна информация TCP, например, TCP/IP-адрес клиентского запроса! Проблема в том, что для того, чтобы объявить службу в сети, мне нужно получить TCP-адрес запроса, чтобы иметь возможность перенаправлять клиентов на эту службу. В этом случае брокер является центральным «сервисным реестром». Однако, имея службы ZeroMQ с обеих сторон, я не вижу возможности получить эту информацию.

Что я делаю сейчас, так это устанавливаю фиктивное соединение с брокером, используя стандартный сокет, после того, как соединение установлено, я беру IP-адрес, используемый для этого соединения, и снова закрываю соединение. Полученный IP-адрес теперь используется для привязки к нему с помощью сокета ZeroMQ на произвольном порту.

Я думаю, что это решение является самым уродливым из возможных, поэтому: какое решение этой проблемы лучше?

Привет.


person AlexLiesenfeld    schedule 30.01.2013    source источник


Ответы (4)


0MQ не предоставляет адреса пиров по ряду причин. Это также не очень полезно, поскольку вам действительно нужна конечная точка для получения соединений, а не адрес, по которому было установлено соединение.

Что я обычно делаю, и это достаточно элегантно, так это привязываю службу к эфемерному порту, получаю конечную точку полного соединения ("tcp://ipaddress:port") и отправляю эту строку каким-то образом, либо широковещательно на одноранговые узлы, либо на центральный реестр и т. д. вместе с моим именем службы. Затем одноранговые узлы, которые хотят подключиться обратно, могут взять имя службы, найти мою конечную точку и снова подключиться ко мне.

person Pieter Hintjens    schedule 30.01.2013
comment
Не могли бы вы более подробно объяснить «привязать службу к эфемерному порту, получить конечную точку полного соединения (tcp://ipaddress:port)»? Мне нужно именно это. Как бы Вы это сделали? Кстати, я ЛЮБЛЮ 0MQ, спасибо за это!!! знак равно - person immerhart; 25.02.2014
comment
Я только что опубликовал более актуальный ответ, а затем заметил, кто разместил этот ответ ... Я должен сказать спасибо за вашу работу! Мне очень нравится работать с 0MQ. Я так многому научился, копаясь в коде, пытаясь понять, как он работает. - person 01BTC10; 23.02.2017

В ZMQ 4.x вы можете получить свойство строки "Peer-Address" или свойство "Identity". http://api.zeromq.org/4-2:zmq-msg-gets

Identity устанавливается в другом узле перед connect(). http://api.zeromq.org/4-2:zmq-setsockopt#toc20

Например,

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");

Затем другая сторона:

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

Я использую CppZmq, кстати, вы сможете легко найти соответствующие вызовы.

person ZHANG Zikai    schedule 02.07.2018

Углубившись в код libzmq, я обнаружил, что библиотека прикрепляет к каждому экземпляру сообщения дескриптор файла, в котором оно было получено.

Это сработало для меня

    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;

Обратите внимание, что FD могут и будут повторно использоваться другими соединениями.

person Akshaye    schedule 01.12.2020

Я работаю с API версии 4.2.1, используя привязку CZMQ, и я нашел решение для своего случая (ZMQ_STREAM). Он работает, устанавливая идентификатор перед подключением.

Соответствующий параметр сокета — «ZMQ_CONNECT_RID».

ZMQ API через zmq_setsockopt()

CZMQ API через zsock_set_connect_rid()

Некоторые коды с отредактированными отредактированными 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);

Затем я получаю эти 2 сообщения, если есть соединение. Первый кадр — это идентификатор, а второй кадр пуст при подключении/отключении для сокетов ZMQ_STREAM.

[Сообщение1]

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

[Сообщение2]

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

Другой вариант — использовать zmq_socket_monitor() или czmq zmonitor. Это было одно из моих первых решений, но я искал что-то более легкое. Я смог получить конечную точку таким образом, не устанавливая идентификатор непосредственно в сокете.

Zactor zmonitor позволяет подписаться на события сокета, а затем отправляет сообщение с 3 кадрами:

[009] CONNECTED
[002] 14
[021] tcp://127.0.0.1:33445
person 01BTC10    schedule 23.02.2017