如果客户端无法连接到服务器,则 ZeroMQ 超时

问题描述 投票:0回答:1

我想要一对独占的 2 个套接字,以允许 2 个独立应用程序之间进行双边通信。我使用 ZeroMQ

cppzmq

在客户端中,我通过握手检查服务器是否处于活动状态。 当我启动客户端时,可能会出现服务器尚未在线的情况。 这会导致客户端此时挂起,我需要强制退出应用程序。

我正在尝试在客户端实现超时,在未收到握手 OK 消息后退出应用程序。我想我可以用

ZMQ_CONNECT_TIMEOUT
ZMQ_SNDTIMEO
ZMQ_RCVTIMEO
来做到这一点。不幸的是,这并没有按照我的预期工作,客户端在程序结束时一直挂起。

如何在程序返回时停止所有阻塞操作?请注意,这是一个 MVCE,我正在一个更大的应用程序中运行它。因此,简单地检查

if (incoming_msg != "OK") exit(0);
在这里可以工作,但不是一个有用的解决方案。

服务器:

// server.cpp
#include <iostream>
#include <zmq.hpp>

int main()
{
    zmq::context_t context(1);
    zmq::socket_t socket(context, zmq::socket_type::pair);
    socket.bind("tcp://*:5555");

    while (true)
    {
        zmq::message_t incoming;
        auto ret = socket.recv(incoming, zmq::recv_flags::none);
        std::string incoming_str = incoming.to_string();
        std::cout << "Received request: " << incoming_str << std::endl;

        if (incoming_str == "connected")
        {
            std::cout << "  Sending OK" << std::endl;
            zmq::message_t ack(2);
            memcpy(ack.data(), "OK", 2);
            socket.send(ack, zmq::send_flags::none);
        }
    }

    return 0;
}

客户:

// client.cpp
#include <iostream>
#include <zmq.hpp>

int main()
{
    zmq::context_t context(1);
    zmq::socket_t socket(context, zmq::socket_type::pair);
    int timeout_ms = 100;
    socket.setsockopt(ZMQ_CONNECT_TIMEOUT, timeout_ms);
    socket.setsockopt(ZMQ_SNDTIMEO, timeout_ms);
    socket.setsockopt(ZMQ_RCVTIMEO, timeout_ms);
    socket.connect("tcp://localhost:5555");

    // send "connected"
    zmq::message_t msg(9);
    memcpy(msg.data(), "connected", 9);
    socket.send(msg, zmq::send_flags::none);

    // receive "OK"
    zmq::message_t incoming;
    auto ret = socket.recv(incoming, zmq::recv_flags::none);
    std::string incoming_str = incoming.to_string();

    std::cout << "Received from server: " << incoming_str << std::endl;

    return 0;
}
c++ sockets connection zeromq
1个回答
0
投票

“如何在程序返回时停止所有阻塞操作”

  • 在应用程序终止之前销毁 zmq::context 对象。这会做两件事
    • 解除所有阻塞套接字调用(例如您的recv)
    • 阻塞自身,直到所有 zmq 套接字都关闭

然后你有责任处理未阻塞的recv并关闭套接字。 检查返回值,如果其 ==

ETERM
则关闭套接字。那时(如果所有套接字都关闭)zmq::context 将解除阻止/继续,并且您的应用程序将退出。

© www.soinside.com 2019 - 2024. All rights reserved.