#include #include #include #include #include "proto/service.pb.h" #include using namespace mesytec; using namespace mesytec::mnode; using namespace std::literals; class PingClient: public nng::AsyncReqWork { public: explicit PingClient(nng_socket socket) : AsyncReqWork(socket) { } nng::unique_msg make_request() override { ping_.set_peer_id(peer_id); ping_.set_sequence_number(sequence_number++); return nng::make_message(ping_.SerializeAsString()); } void handle_reply(nng::unique_msg &&request, nng::unique_msg &&reply) override { ping_.ParseFromArray(nng_msg_body(request.get()), nng_msg_len(request.get())); pong_.ParseFromArray(nng_msg_body(reply.get()), nng_msg_len(reply.get())); if (ping_.sequence_number() != pong_.sequence_number()) spdlog::error("Work: sequence_number mismatch: ping={}, pong={}", ping_.sequence_number(), pong_.sequence_number()); if (ping_.peer_id() != pong_.peer_id()) spdlog::error("Work: peer_id mismatch: ping={}, pong={}", ping_.peer_id(), pong_.peer_id()); ++num_transactions; } void report() { spdlog::info("PingClient, peer_id={}, transactions={}", peer_id, num_transactions); } private: proto::Ping ping_; proto::Pong pong_; size_t sequence_number = 1; static std::atomic next_peer_id; size_t peer_id = next_peer_id++; size_t num_transactions = 0; }; std::atomic PingClient::next_peer_id; int main() { spdlog::set_level(spdlog::level::info); auto socket = nng::make_req_socket(1000); if (int res = nng_dial(socket, "tcp://localhost:5555", nullptr, NNG_FLAG_NONBLOCK)) { nng::mnode_nng_error("nng_dial", res); return res; } mvlc::util::Stopwatch sw; std::vector> clients; for (int i = 0; i < 10; ++i) clients.emplace_back(std::make_unique(socket)); for (auto &client: clients) client->work(); for (;;) { nng_msleep(100); if (sw.get_interval() >= 1s) { for (auto &client: clients) client->report(); sw.interval(); } } return 0; }