Я пытаюсь воссоздать пример «Маршрутизатор-маршрутизатор» из 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;
}
Измените свой 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!")
};
Есть два изменения:
client.connect(...)
вернется. Небольшая задержка гарантирует, что соединение будет установлено и сообщение будет доставлено.str_buffer
.По поводу подключения:
Ретрансляция с задержкой — это грубо и не идеально. Лучшим решением, вероятно, было бы отслеживать состояние соединения через zmq_socket_monitor (или его эквивалент cppzmq) и ждать ZMQ_EVENT_CONNECTED
. Я надеюсь, что это событие будет доставлено после того, как соединение будет полностью установлено (обмен идентификаторами маршрутизации), но я не уверен. Стоит попробовать.
Для принятия ответов не требуется репутация ;-). В любом случае, хороший первый вопрос!
Спасибо! Я поддержу и приму ответ, как только у меня будет достаточная репутация.