Cppzmq — связь между маршрутизаторами зависает при первом подключении

Я пытаюсь воссоздать пример «Маршрутизатор-маршрутизатор» из PyZMQ, используя cppzmq. Я протестировал версию Python, и поведение соответствует ожиданиям (т. е. клиент подключается к серверу, сервер отправляет ответ).

Однако моя версия C++ зависает при начальном подключении (или выдает ошибку о недоступности хоста, если установлен router_mandatory). Изменение типа клиентского сокета на дилерский приводит к ожидаемому потоку сообщений.

Я подозреваю, что я как-то перепутал идентификаторы/маршрутизацию, но я слишком застрял, чтобы понять, где я ошибся.

сервер.cpp

#include <zmq.hpp>
#include <zmq_addon.hpp>
#include <iostream>
#include <vector>
#include <string>

int main() {
    zmq::context_t context(1);
    zmq::socket_t server(context, zmq::socket_type::router);
    server.set(zmq::sockopt::routing_id, "server");
    server.bind("tcp://*:4000");

    while (true) {
        std::cout << "Waiting for msg" << std::endl; 

        std::vector<zmq::message_t> recv_msgs;
        zmq::recv_multipart(server, std::back_inserter(recv_msgs));

        std::string received_message(static_cast<char*>(recv_msgs[1].data()), recv_msgs[1].size());
        std::cout << "Received message: " << received_message << std::endl;

        server.send(recv_msgs[0], zmq::send_flags::sndmore);
        server.send(zmq::message_t(), zmq::send_flags::sndmore);
        server.send(zmq::buffer("Response from server"), zmq::send_flags::none);
    }

    return 0;
}

клиент.cpp

#include <zmq.hpp>
#include <zmq_addon.hpp>
#include <array>
#include <iostream>
#include <string>

int main() {
    zmq::context_t context(1);
    zmq::socket_t client(context, zmq::socket_type::router);
    client.set(zmq::sockopt::routing_id, "client");
    client.connect("tcp://127.0.0.1:4000");

    // Send a request to the server
    std::array<zmq::const_buffer, 3> bufs = {
      zmq::buffer("server"), // set identity of server we try to reach
      zmq::str_buffer(""),
      zmq::str_buffer("Hello, Server!")
    };
    zmq::send_multipart(client, bufs);

    // Receive the response
    zmq::message_t reply;
    zmq::message_t identity;
    client.recv(identity, zmq::recv_flags::none);
    client.recv(reply, zmq::recv_flags::none);

    std::string reply_message(static_cast<char*>(reply.data()), reply.size());
    std::cout << "Received reply: " << reply_message << std::endl;

    return 0;
}
  • Я прочитал руководство
  • Я проверил наличие подобных проблем на github
  • Я попробовал несколько вариантов идентификаторов, буферов, составных сообщений и типов сокетов (в качестве проверки работоспособности).
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Измените свой client.cpp в соответствии со следующим патчем:

--- client1.cc  2024-08-18 21:07:00.000000000 +0000
+++ client2.cc  2024-08-18 21:08:00.000000000 +0000
@@ -1,18 +1,21 @@
 #include <zmq.hpp>
 #include <zmq_addon.hpp>
 #include <array>
+#include <chrono>
 #include <iostream>
 #include <string>
+#include <thread>
 
 int main() {
     zmq::context_t context(1);
     zmq::socket_t client(context, zmq::socket_type::router);
     client.set(zmq::sockopt::routing_id, "client");
     client.connect("tcp://127.0.0.1:4000");
+    std::this_thread::sleep_for(std::chrono::milliseconds{100});
 
     // Send a request to the server
     std::array<zmq::const_buffer, 3> bufs = {
-      zmq::buffer("server"), // set identity of server we try to reach
+      zmq::str_buffer("server"), // set identity of server we try to reach
       zmq::str_buffer(""),
       zmq::str_buffer("Hello, Server!")
     };

Есть два изменения:

  • Я добавил небольшую задержку после подключения. Это необходимо, поскольку ZeroMQ работает асинхронно и работает в фоновом потоке. Поэтому не гарантируется, что соединение будет установлено, когда client.connect(...) вернется. Небольшая задержка гарантирует, что соединение будет установлено и сообщение будет доставлено.
  • Я изменил первую часть сообщения, состоящего из нескольких частей, на str_buffer.

По поводу подключения: Ретрансляция с задержкой — это грубо и не идеально. Лучшим решением, вероятно, было бы отслеживать состояние соединения через zmq_socket_monitor (или его эквивалент cppzmq) и ждать ZMQ_EVENT_CONNECTED. Я надеюсь, что это событие будет доставлено после того, как соединение будет полностью установлено (обмен идентификаторами маршрутизации), но я не уверен. Стоит попробовать.

Спасибо! Я поддержу и приму ответ, как только у меня будет достаточная репутация.

user26869366 19.08.2024 08:59

Для принятия ответов не требуется репутация ;-). В любом случае, хороший первый вопрос!

sedor 19.08.2024 20:19

Другие вопросы по теме