小能豆

可以在多线程之间使用zmq的pub sub模式吗

javascript

我在qt程序多线程之间使用了zmq的pub sub模式,使用的是环回地址。但我发现无法接收到数据。
我不想使用push_pull模式,我有多个接收数据的线程,当前通过pub_sub模式使用多个主题发送接收。我想知道是否是我代码的问题,同样的接收发送逻辑我放在两个进程之间通信正常,另外,我可以在pub_sub模式中使用inproc协议进行多线程通信吗,


阅读 46

收藏
2024-06-18

共1个答案

小能豆

在 Qt 程序中使用 ZeroMQ (zmq) 的 PUB-SUB 模式进行多线程通信时,如果遇到无法接收到数据的问题,可能有几个原因:

  1. 地址绑定问题:确保发布者和订阅者绑定和连接的地址正确。如果使用环回地址 (localhost127.0.0.1),确保端口没有被其他程序占用。

  2. 订阅主题问题:订阅者需要明确订阅某个主题。即使发布者发送数据,订阅者也需要订阅对应的主题才能接收到数据。

  3. 多线程环境问题:ZeroMQ 的 PUB-SUB 模式在多线程环境下需要小心处理。ZeroMQ 的上下文 (zmq::context_t) 需要在多线程之间共享,但套接字不能在多线程之间共享。

  4. 协议问题PUB-SUB 模式可以使用 inproc 协议进行多线程通信,但需要确保上下文在同一进程内共享。

下面是一个示例,展示了如何在 Qt 程序中使用 ZeroMQ 的 PUB-SUB 模式进行多线程通信,同时使用 inproc 协议:

示例代码

Publisher 线程

#include <QThread>
#include <zmq.hpp>

class PublisherThread : public QThread
{
    Q_OBJECT
public:
    explicit PublisherThread(zmq::context_t &context, QObject *parent = nullptr)
        : QThread(parent), context(context) {}

protected:
    void run() override {
        zmq::socket_t publisher(context, ZMQ_PUB);
        publisher.bind("inproc://pubsub");

        while (true) {
            zmq::message_t message("Hello", 5);
            publisher.send(message, zmq::send_flags::none);
            QThread::sleep(1);  // Send message every second
        }
    }

private:
    zmq::context_t &context;
};

Subscriber 线程

#include <QThread>
#include <zmq.hpp>
#include <QDebug>

class SubscriberThread : public QThread
{
    Q_OBJECT
public:
    explicit SubscriberThread(zmq::context_t &context, QObject *parent = nullptr)
        : QThread(parent), context(context) {}

protected:
    void run() override {
        zmq::socket_t subscriber(context, ZMQ_SUB);
        subscriber.connect("inproc://pubsub");
        subscriber.setsockopt(ZMQ_SUBSCRIBE, "", 0);  // Subscribe to all topics

        while (true) {
            zmq::message_t message;
            subscriber.recv(message, zmq::recv_flags::none);
            qDebug() << "Received message:" << QString::fromStdString(message.to_string());
        }
    }

private:
    zmq::context_t &context;
};

主函数

#include <QCoreApplication>
#include <zmq.hpp>
#include "PublisherThread.h"
#include "SubscriberThread.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    zmq::context_t context(1);

    PublisherThread publisherThread(context);
    SubscriberThread subscriberThread(context);

    publisherThread.start();
    subscriberThread.start();

    return a.exec();
}

注意事项

  1. 上下文共享:确保 zmq::context_t 在所有线程间共享。
  2. 订阅所有主题:示例中,订阅者使用 ZMQ_SUBSCRIBE 订阅所有主题。如果只想订阅特定主题,需要修改订阅选项。
  3. 线程安全:ZeroMQ 的套接字不允许在多线程间共享。每个线程应有自己独立的套接字,但可以共享上下文。

通过这种方式,你可以在 Qt 程序中使用 ZeroMQ 的 PUB-SUB 模式和 inproc 协议进行多线程通信。如果仍然无法接收到数据,请确保各个线程正常启动,并且发布者和订阅者的地址和端口设置正确。

2024-06-18