Qt-ZMQ的使用补充(pub-sub)

之前写过一篇Qt使用ZMQ的博客Qt网络编程-ZMQ的使用,本文是其的补充部分。

Linux上编译使用

首先这次实在Linux上进行演示,下载zmq源码,安装cmake,使用cmake进行编译。下载之后解压:

输入命令:

cd ..mkdir zmqbuildcmake ../libzmq-master

会有以下输出:

输入:

make -j16

等待编译完成:

在该目录下即可找到对应的动态库文件:

新建工程,然后将头文件和动态库文件放进来,然后在工程文件中引入头文件和库文件。

这是我的文件结构:

工程文件:


#引入libzmq头文件和库
INCLUDEPATH += $PWD/zmq/includeunix {LIBS += -L$$PWD/zmq/libLIBS += -lzmq
}

基于TCP通信 

在之前的博客中发布和订阅段有对应的bind和connect方法进行绑定和连接:

bool ZmqPublisher::bind(quint16 port) {QString arg = QString("tcp://*:%1").arg(port);int rc = zmq_bind(socket, arg.toUtf8().constData());return rc == 0;
}bool ZmqSubscriber::connectTo(quint16 port) {QString arg = QString("tcp://localhost:%1").arg(port);int rc = zmq_connect(socket, arg.toUtf8().constData());return rc == 0;
}

这两个方法内部使用tcp进行网络通信。bind和connect也可以绑定具体的ip和端口,以下是扩充方法:

bool ZmqPublisher::bind(const QString &ip, quint16 port)
{QString arg = QString("tcp://%1:%2").arg(ip).arg(port);int rc = zmq_bind(socket, arg.toUtf8().constData());return rc == 0;
}bool ZmqSubscriber::connectTo(const QString &ip, quint16 port)
{QString arg = QString("tcp://%1:%2").arg(ip).arg(port);int rc = zmq_connect(socket, arg.toUtf8().constData());return rc == 0;
}

写一个测试程序进行测试:

可以看到发布端bind后对应的tcp开始listen了。

然后订阅段进行connect:

对应的tcp连接已经建立。

测试通信:

通信正常。

基于本地文件通信

zmq除了借助TCP网络进行进程间通信还可以使用 文件进行进程间通信,这里封装对应的方法:

bool ZmqPublisher::bind(const QString &path)
{int rc = zmq_bind(socket, path.toUtf8().constData());return rc == 0;
}bool ZmqSubscriber::connectTo(const QString &path)
{int rc = zmq_connect(socket, path.toUtf8().constData());return rc == 0;
}

直接传入对应的地址,当然这里path传“tcp://{ip}:{port}”这种也行,这样就是前面提到的网络通信了。本地文件通信传入格式是“ipc://{path}”。

可以看到生成了一个文件:

使用命令查看文件属性:

这就是进行通信的socket文件。订阅端进行connect:

使用命令查看连接情况,之前在TCP和UDP通信的博客中讲到了使用netstat查看网络连接,实际上netstat也可以查看这种本地文件连接:

 使用ss命令也可以查看,ss命令功能比netstat命令广泛,后续推荐使用ss命令。

通信测试:

注意事项:

1.注意对应文件的路径,因为我的示例中socket文件在执行文件同级目录下所以使用的是相对路径。(bind和connect时传入完整路径:比如bind("/home/pc/zkh/projects/build-zmqproject-Desktop_Qt_5_12_12_GCC_64bit-Debug/test"))

2.直接使用本地文件bind(ipc://{path})这种方式通信目前不能跨主机而且在windows上无效 。

 代码优化

之前写的代码调用比较麻烦,其中要在调用处新建线程类,然后订阅部分每connect一个都要新建sub对象,所以我在pub和sub类之上在新建一个类ZmqPubSub,对二者进行管理,调用者只需要新建ZmqPubSub这一个类就可以进行发布订阅消息处理相关操作,而且方便处理多个订阅端,以下是代码:

头文件:

#ifndef ZMQPUBSUB_H
#define ZMQPUBSUB_H#include <QObject>class QThread;
class ZmqSubscriber;
class ZmqPublisher;
class ZmqPubSub : public QObject
{Q_OBJECT
public:explicit ZmqPubSub(QObject *parent = nullptr);void init(const QString &pubPath,const QStringList &subPaths);signals:void dataReceived(const QByteArray &data);public slots:void publishData(const QByteArray &data);private:bool m_Inited;ZmqPublisher *m_Pub;QList<ZmqSubscriber *>m_Subs;QList<QThread *>m_Ths;};#endif // ZMQPUBSUB_H

源文件:

#include "zmqpubsub.h"
#include "zmqpublisher.h"
#include "zmqsubscriber.h"
#include <QThread>
#include <QDataStream>ZmqPubSub::ZmqPubSub(QObject *parent) : QObject(parent),m_Inited(false),m_Pub(nullptr)
{}void ZmqPubSub::init(const QString &pubPath, const QStringList &subPaths)
{if(m_Inited)return;QThread *pubTh=new QThread;m_Pub=new ZmqPublisher;m_Pub->bind(pubPath);m_Pub->moveToThread(pubTh);pubTh->start();m_Ths.append(pubTh);for(const QString &subPath:subPaths){QThread *subTh=new QThread;ZmqSubscriber *sub=new ZmqSubscriber;sub->connectTo(subPath);sub->moveToThread(subTh);subTh->start();m_Subs.append(sub);m_Ths.append(subTh);connect(sub, &ZmqSubscriber::dataReceived,this,&ZmqPubSub::dataReceived);QMetaObject::invokeMethod(sub, &ZmqSubscriber::procesMessage);}m_Inited=true;
}void ZmqPubSub::publishData(const QByteArray &data)
{if(m_Inited){m_Pub->publishData(data);}
}

调用的时候只需要新建ZmqPubSub类即可,线程相关在内部自行处理 ,init方法初始化可以处理多个订阅端的问题。一个类实现发布订阅功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/73412.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++的名称空间

C++的名称空间(namespace)是一种用于组织代码、防止命名冲突的机制。以下是名称空间的详细说明和使用建议: 1. 名称空间的定义 使用namespace关键字定义,内部可包含变量、函数、类等: namespace MyNamespace {int a;void func() {} }2. 访问方式 作用域解析运算符:::显…

记录致远OA服务器硬盘升级过程

前言 日常使用中OA系统突然卡死&#xff0c;刷新访问进不去系统&#xff0c;ping服务器地址正常&#xff0c;立马登录服务器检查&#xff0c;一看磁盘爆了。 我大脑直接萎缩了&#xff0c;谁家OA系统配400G的空间啊&#xff0c;过我手的服务器没有50也是30台&#xff0c;还是…

[测试]自动化的概念 及使用Selenium实现Web自动化测试

文章目录 1. 自动化1.1 自动化概念1.2 自动化分类1.2.1 接口自动化1.2.2 UI自动化 1.3 自动化测试金字塔 2. Web自动化测试2.1 驱动 3. Selenium3.1 一个简单的Web自动化示例3.2 Selenium 驱动 浏览器的工作原理 1. 自动化 1.1 自动化概念 自动化是指自动地代替人的行为完成…

Python教程(三):类对象、闭包、装饰器、类型注解、MRO

Python总结&#xff08;三&#xff09; 本系列其他教程&#xff1a; Python教程(一)&#xff1a;基本语法、流程控制、数据容器 Python教程(二)&#xff1a;函数、异常、模块&包、文件读取、常用模块 文章目录 Python总结&#xff08;三&#xff09;一、类&对象1.1 成…

什么是 HTML?

HTML 是用来描述网页的一种语言。 HTML 指的是超文本标记语言: HyperText Markup LanguageHTML 不是一种编程语言&#xff0c;而是一种标记语言标记语言是一套标记标签 (markup tag)HTML 使用标记标签来描述网页HTML 文档包含了HTML 标签及文本内容HTML文档也叫做 web 页面 HT…

【Hadoop】Hadoop的简要介绍

Hadoop是一个由Apache基金会所开发的分布式系统基础架构&#xff0c;主要用于解决海量数据的存储及分析计算问题。以下是对Hadoop的详细介绍&#xff1a; 目录 一、Hadoop的起源与发展 二、Hadoop的核心组件 1.HDFS&#xff1a; 2.MapReduce&#xff1a; 3.YARN&#xff…

如何用AI制作PPT,轻松实现高效演示

如何用AI制作PPT&#xff0c;轻松实现高效演示&#xff01;在今天这个快节奏的时代&#xff0c;我们的工作方式越来越依赖智能工具。而当涉及到演示文稿时&#xff0c;传统的PPT制作方式往往繁琐且耗时。很多人一提到制作PPT就头大&#xff0c;特别是在内容需要多次修改、调整布…

Canoe Panel基础功能介绍

文章目录 一、新建 Panel 面板二、添加 Panel 面板三、删除 Panel 面板四、Panel视图&#xff08;views&#xff09;五、控件布局1. 对齐布局2. 控件大小布局 六、Panel 属性设置1. 设置背景色和背景图片2. 调整 Panel 画布大小 提示&#xff1a;如何使用 Panel 面板参考 CANoe…

超声重建,3D重建 超声三维重建,三维可视化平台 UR 3D Reconstruction

1. 超声波3D重建技术的实现方法与算法 技术概述 3D超声重建是一种基于2D超声图像生成3D体积数据的技术&#xff0c;广泛应用于医学影像领域。通过重建和可视化三维结构&#xff0c;3D超声能够显著提高诊断精度和效率&#xff0c;同时减少医生的脑力负担。本技术文档将详细阐述…

2.2 企业级ESLint/Prettier规则定制

文章目录 1. 为什么需要企业级代码规范2. 工具选型对比3. 完整配置流程3.1 项目初始化3.2 ESLint深度配置3.3 Prettier精细配置3.4 解决规则冲突4. 高级定制方案4.1 自定义ESLint规则4.2 扩展Prettier插件5. 团队协作策略5.1 配置共享方案5.2 版本控制策略6. CI/CD集成7. 常见问…

QT创建项目(项目模板、构建系统、选择类、构建套件)

1. 项目模版 项目类型界面技术适用场景核心依赖模块开发语言Qt Widget ApplicationC Widgets传统桌面应用&#xff08;复杂控件&#xff09;Qt WidgetsCQt Console Application无 GUI命令行工具、服务Qt CoreCQt Quick ApplicationQML/Quick现代跨平台应用&#xff08;动画/触…

oracle11.2.0.4 RAC 保姆级静默安装(二) DB数据库软件

1.响应文件配置 [rootdb11g1 software]# su - oracle [oracledb11g1 ~]$ cd /software/database/ [oracledb11g1 database]$ cd response/ [oracledb11g1 response]$ vi db_install.rsp oracle.install.optionINSTALL_DB_SWONLY ORACLE_HOSTNAMEdb11g1 UNIX_GROUP_NAME…

日语学习-日语知识点小记-构建基础-JLPT-N4N5阶段(22):给与和得到相关用法

日语学习-日语知识点小记-构建基础-JLPT-N4&N5阶段(22):给与和得到相关用法 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) あげます :给(2)もらいます(いただきます) 得到。(3) くれました :主要是给我。3、单词(1)日语单词(2)日语片假名…

Qt5中视口(ViewPort)与窗口(Window)

在Qt中&#xff0c;setViewport和setWindow是用于控制坐标系映射的核心方法&#xff0c;二者共同决定了绘图逻辑与物理设备之间的转换关系。以下是关键点总结&#xff1a; ‌1. 视口&#xff08;Viewport&#xff09;与窗口&#xff08;Window&#xff09;的核心区别‌ ‌视口…

迪威 3D 模型发布系统:制造业产品展示革新利器

在竞争激烈的制造业领域&#xff0c;如何将产品全方位、直观地呈现给客户&#xff0c;成为企业脱颖而出的关键。传统的产品展示方式往往受限于平面资料或有限的实物展示&#xff0c;难以让客户深入了解产品的复杂结构与精妙细节。迪威 3D 模型发布系统的问世&#xff0c;为制造…

EasyCVR安防视频汇聚平台助力工业园区构建“感、存、知、用”一体化智能监管体系

在现代工业园区的安全管理和高效运营中&#xff0c;视频监控系统扮演着不可或缺的角色。然而&#xff0c;随着园区规模的扩大和业务的复杂化&#xff0c;传统的视频监控系统面临着诸多挑战&#xff0c;如设备众多难以统一管理、数据存储分散、智能分析能力不足、信息利用率低下…

解决 Redis 后台持久化失败的问题:内存不足导致 fork 失败

文章目录 解决 Redis 后台持久化失败的问题&#xff1a;内存不足导致 fork 失败问题背景与成因解决方案修改内核参数 vm.overcommit_memory增加系统内存或 Swap 空间调整 Redis 配置 stop-writes-on-bgsave-error 在 Docker 环境中的注意事项总结 解决 Redis 后台持久化失败的问…

反射、反射调用以及修改成员变量,成员方法,构造函数、反射的应用

DAY11.2 Java核心基础 反射&#xff08;第二弹&#xff09; 第一弹请访问链接&#xff1a; 反射&#xff08;第一篇&#xff09; getMethod(String name, Class… parameterTypes)getMethods()getDeclaredMethod(String name,Class… parameterTypes)getDeclaredMethods() …

【鸿蒙开发】Hi3861学习笔记- 外部中断

00. 目录 文章目录 00. 目录01. 概述02. EXTI相关API03. 硬件设计04. 软件设计05. 实验现象06. 附录 01. 概述 我们在做按键控制实验时&#xff0c;虽然能实现 IO 口输入功能&#xff0c;但代码是一直在检测 IO 输入口的变化&#xff0c;因此效率不高&#xff0c;特别是在一些…

使用 crontab 定时同步服务器文件到本地

https://www.dong-blog.fun/post/1987 1. 安装 sshpass sshpass 是一个可以自动输入密码的工具。如果未安装&#xff0c;运行以下命令安装&#xff1a; • 对于 Debian/Ubuntu 系统&#xff1a; apt update && apt install sshpass• 对于 CentOS/RHEL 系统&#xf…