Qt网络编程-ZMQ的使用

不同主机或者相同主机中不同进程之间可以借助网络通信相互进行数据交互,网络通信实现了进程之间的通信。比如两个进程之间需要借助UDP进行单播通信,则双方需要知道对方的IP和端口,假设两者不在同一主机中,如下示意图:

主机1中的进程A想要与主机2中的进程B进行通信,则首先他们之间需要知道对方所在主机的IP地质以及对方所绑定的端口,好比A和B住在同一个小区(同一个局域网内),A派人给B送信则需要制度B所住的楼栋(主机IP地址)以及B的门牌号(绑定的IP地址)。

不同主机之间的不同进程可以借助网络套接字进行通信,同主机内也是如此,关于进程间通信我之前也写过对应博客:

linux消息队列的简单使用_linux消息队列发送消息为0-CSDN博客

QLocalSocket、QLocalServer实现本地进程通信简单实例_qt vs2015 进程间通信-CSDN博客

这里使用TCP或者UDP进行同一主机内通信也是没有问题的,比如同主机内不同进程使用UDP套接字进行通信,两者可以根据都绑定本机IP127.0.0.1,然后各自根据配置文件绑定不同端口,最后通过QUdpSocket进行数据交互。使用QTcp也是类似,只不过各进程需要指定对应的服务器和客户端,本地进程间通信如果自己实现我还是推进使用QUdpSocket,因为UDP面向报文,无需建立链接,除了单播还可以广播、组播,而且因为处于同一主机,所以基本不用考虑整个报文丢失的问题。第三方库可以采用ZMQ进行进程间通信

第三方库ZeroMQ(也称为ZMQ)是一个流行的消息传递库,它提供了简单而高效的消息传递模式,用于在应用程序之间进行通信。ZeroMQ(ZMQ)可以基于多种传输协议进行通信,包括TCP、UDP、in-process(进程内通信)等。它提供了不同的传输协议来满足不同的通信需求。

ZMQ下载:

The ZeroMQ project · GitHub

下载之后直接解压:

ZMQ编译:

环境:Windows,Qt515.2,VS2022

使用cmake打开:

 

 

完成之后打开对应生成的目录:

使用VS打开对应工程:

编译对应Debug版和release版的库:

 

等待编译完成:

同样方法编译生成Debug版:

生成动态库对应位置:

动态导入库位置:

在工程引入,文件结构:

ZMQ通信主要有REP/REQ、PUB/SUB、PUSH/PULL三种类型,本文主要介绍第二种PUB/SUB即发布/订阅模式 。

工程文件中引入ZMQ头文件以及库文件:

#引入libzmq头文件和库
INCLUDEPATH += $PWD/zmq/includewin32 {LIBS += -L$$PWD/zmq/libCONFIG(release, debug|release) {LIBS += -llibzmq-v143-mt-4_3_6}CONFIG(debug, debug|release) {LIBS += -llibzmq-v143-mt-gd-4_3_6}
}

发布类ZmqPublisher

头文件:

#ifndef ZMQPUBLISHER_H
#define ZMQPUBLISHER_H#include <QObject>class ZmqPublisher : public QObject {Q_OBJECT
public:explicit ZmqPublisher(QObject *parent = nullptr);~ZmqPublisher();bool bind(quint16 port);signals:public slots:void publishData(const QByteArray &data);private:void *context;void *socket;
};#endif // ZMQPUBLISHER_H

源文件:

#include "zmqpublisher.h"
#include "zmq/include/zmq.h"
#include <QDebug>ZmqPublisher::ZmqPublisher(QObject *parent) : QObject{parent} {context = zmq_ctx_new();socket = zmq_socket(context, ZMQ_PUB);
}ZmqPublisher::~ZmqPublisher() {zmq_close(socket);zmq_ctx_destroy(context);
}bool ZmqPublisher::bind(quint16 port) {QString arg = QString("tcp://*:%1").arg(port);int rc = zmq_bind(socket, arg.toUtf8().constData());return rc == 0;
}void ZmqPublisher::publishData(const QByteArray &data) {zmq_send(socket, data, data.size(), 0);
}

订阅类ZmqSubscriber

头文件:

#ifndef ZMQSUBSCRIBER_H
#define ZMQSUBSCRIBER_H#include <QObject>class ZmqSubscriber : public QObject {Q_OBJECT
public:explicit ZmqSubscriber(QObject *parent = nullptr);~ZmqSubscriber();bool connectTo(quint16 port);public slots:void procesMessage();signals:void dataReceived(const QByteArray &data);private:void *context;void *socket;
};#endif // ZMQSUBSCRIBER_H

源文件:

#include "zmqsubscriber.h"
#include "zmq/include/zmq.h"ZmqSubscriber::ZmqSubscriber(QObject *parent) : QObject{parent} {context = zmq_ctx_new();socket = zmq_socket(context, ZMQ_SUB);zmq_setsockopt(socket, ZMQ_SUBSCRIBE, "", 0);
}ZmqSubscriber::~ZmqSubscriber() {zmq_close(socket);zmq_ctx_destroy(context);
}bool ZmqSubscriber::connectTo(quint16 port) {QString arg = QString("tcp://localhost:%1").arg(port);int rc = zmq_connect(socket, arg.toUtf8().constData());return rc == 0;
}void ZmqSubscriber::procesMessage() {while (true) {zmq_msg_t message;zmq_msg_init(&message);zmq_recvmsg(socket, &message, 0);QByteArray data(static_cast<const char *>(zmq_msg_data(&message)),zmq_msg_size(&message));emit dataReceived(data);zmq_msg_close(&message);}
}

调用示例:

新建对应发布类以及线程,将发布类移入线程:

    QThread *m_PubThread;QThread *m_SubThread;ZmqPublisher *m_Publisher;ZmqSubscriber *m_Subscriber;

使用线程调用:

    m_PubThread = new QThread;m_SubThread = new QThread;m_Publisher = new ZmqPublisher;m_Subscriber = new ZmqSubscriber;m_Publisher->moveToThread(m_PubThread);m_Subscriber->moveToThread(m_SubThread);connect(this, &MainWindow::publishData, m_Publisher,&ZmqPublisher::publishData);connect(m_Subscriber, &ZmqSubscriber::dataReceived,[=](const QByteArray &data) {//TODO 处理zmq接收数据});m_PubThread->start();m_SubThread->start();QMetaObject::invokeMethod(m_Subscriber, &ZmqSubscriber::procesMessage);

运行效果:

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

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

相关文章

查看系统进程信息的Tasklist命令

Tasklist命令是一个用来显示运行在本地计算机上所有进程的命令行工具&#xff0c;带有多个执行参数。另外&#xff0c;Tasklist可以代替Tlist工具。通过任务管理器&#xff0c;可以查看到本机完整的进程列表&#xff0c;而且可以通过手工定制进程列表方式获得更多进程信息&…

7 scala的类构造器

在创建对象的时候&#xff0c;需要调用类的构造器。Scala 提供了主构造器和辅助构造器。 1 主构造器 与 Java 一样&#xff0c;如果我们没有特别定义&#xff0c;那么 Scala 提供的默认构造器是没有参数的。 我们可以在类名后&#xff0c;指定构造器的参数列表&#xff0c;列…

回归预测模型:MATLAB多项式回归

1. 多项式回归模型的基本原理 多项式回归是线性回归的一种扩展&#xff0c;用于分析自变量 X X X与因变量 Y Y Y之间的非线性关系。与简单的线性回归模型不同&#xff0c;多项式回归模型通过引入自变量的高次项来增加模型的复杂度&#xff0c;从而能够拟合数据中的非线性模式。…

【北邮鲁鹏老师计算机视觉课程笔记】02 filter

1 图像的类型 二进制图像&#xff1a; 灰度图像&#xff1a; 彩色图像&#xff1a; 2 任务&#xff1a;图像去噪 噪声点让我们看得难受是因为噪声点与周边像素差别很大 3 均值 滤波核 卷积核 4 卷积操作 对应相乘再累加起来 卷积核记录了权值&#xff0c;把权值套到要卷积…

GPT-4模型的创造力

超级的创造力是GPT-4等高级语言模型的重要特征之一。它们不仅能够精确地模拟和再现各类文本样式、结构和内容&#xff0c;而且在生成新的文本时&#xff0c;能够通过深度学习算法对海量训练数据中捕捉到的模式进行创新性的重组与拓展&#xff1a; 词汇创新&#xff1a;基于已学…

Redis——集群环境部署

一般情况下的Redis&#xff0c;我们都是在一台服务器上进行操作的&#xff0c;也就是说读、写以及备份操作都是在一台Redis服务器上进行的。随着项目访问量的增加&#xff0c;对Redis服务器的操作也更加频繁&#xff0c;虽然Redis读写速度都很快&#xff0c;但是一定程度上也会…

统一身份认证系统架构设计与实践总结

随着互联网的快速发展和应用的普及&#xff0c;人们在各个网站和应用上需要不同的账号和密码进行身份认证。为了解决这个问题&#xff0c;统一身份认证系统应运而生。本文将总结统一身份认证系统的架构设计与实践经验&#xff0c;帮助读者了解如何设计和实现一个高效、安全的统…

〖大前端 - ES6篇②〗- let和const

说明&#xff1a;该文属于 大前端全栈架构白宝书专栏&#xff0c;目前阶段免费&#xff0c;如需要项目实战或者是体系化资源&#xff0c;文末名片加V&#xff01;作者&#xff1a;哈哥撩编程&#xff0c;十余年工作经验, 从事过全栈研发、产品经理等工作&#xff0c;目前在公司…

ORACLE的 软 软 软 解析!

在海鲨数据库架构师精英群里,有位朋友说ORACLE 有 软软软解析. 就是把执行计划缓存在客户端里,从而避免去服务端找执行计划. 他给了个设置方法, Weblogic console->datasource->connectionPool Statement Cache Type >LRU Statement Cache Size100 CURSOR_NUMBER …

求满二叉树两个节点之间的最短距离

求满二叉树两个节点之间的最短距离 using System; using System.Collections.Generic; using System.Linq; using System.Text;namespace FirstSolver {internal class Program{static void Main(string[] args){BinaryTreeNode<int> root1 FullBinaryTree.CreateTree(1…

python实现基数排序

如果在给不同的整形数组排序的时候,一般会这样做,也就是先看最高位,如果最高位数值大的话也就意味着它的数值是最大的,而如果两个数字的最高位的数值是一样的,则继续比较次高位,这样依次去比较可以决定数字的排序。而对于基数排序来说,其思想是与以上的思想是不同的,基…

Node版本管理 - nvm

简介 nvm 允许用户在同一台电脑上安装并管理多个 Node.js 版本并支持快速切换&#xff0c;对于需要在不同的项目中使用不同版本的 Node.js 的开发者来说非常有用。 使用 下载安装后&#xff0c;以管理员身份打开windows控制台。 # 设置下载node安装包&#xff0c;和npm安装…

linux系统非关系型数据库redis常见问题以及好处

redis常见问题以及好处 redis常见问题缓存穿透概念解决方案布隆过滤器缓存空对象 缓存雪崩概念解决方案redis高可用限流降级数据预热 redis好处redis常见性能问题解决方案为redis加密 redis常见问题 缓存穿透 概念 缓存穿透的概念很简单&#xff0c;用户想要查询一个数据&am…

02-实现方法多值返回-pair与truple

在实际的项目开发中&#xff0c;我们经常会遇到返回多个值&#xff0c;通常我们使用Map对象、自定义Class对象等方式封装返回结果。但是这种方式&#xff0c;需要定义大量中间类&#xff0c;影响代码的整体质量。 spring 为我们提供了pair 双值与 triple 三值返回对象。 1、p…

二级C语言笔试6

(总分100,考试时间90分钟) 一、选择题 1. 设有以下语句&#xff1a; charx3&#xff0c;y6&#xff0c;z&#xff1b; zx^y&#xff1c;&#xff1c;2&#xff1b; 则z的二进制值是( )。 A. 00010100 B. 00011011 C. 00011100 D. 00011000 …

从Unity到Three.js(画线组件line)

JavaScript 0基础&#xff0c;只是照着官方文档临摹了下&#xff0c;之后有时间再进行细节学习和功能封装。 import * as THREE from three; //引入threejsconst renderer new THREE.WebGLRenderer();//创建渲染器 //设置渲染范围&#xff0c;当前撑满全屏,屏幕左上角是&…

C++类型转化cast from pointer to smaller type ‘int‘ loses information

代码如下 #include <iostream>int main() {int a 10;std::cout << (int)&a << std::endl;return 0; }编译 这段代码是要将地址转化成整数类型&#xff0c;但是在编译时编译器告诉我们这是错的&#xff0c;因为在C中&#xff0c;将指针转换为int类型的…

Spring IoC容器详解

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 基本概念 Spring IoC容器是Spring框架的核心组件&#xff0c;它实现了控制反转&#xff08;Inversion of Control&#xff0c;IoC&#xff09;的设计原则。IoC是一种编程思…

【前端高频面试题--TypeScript篇】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;前端高频面试题 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 高频前端面试题--Vue3.0篇 什么是TypeScript&#xff1f;TypeScript数据类型TypeScript中命名空…

最关键的十个图像特征

在计算机视觉中&#xff0c;图像特征是用来描述图像中视觉元素的一组属性&#xff0c;它们对于图像识别、分类、检测和分割等任务至关重要。以下是10个在计算机视觉中广泛使用的最重要的图像特征&#xff1a; 颜色直方图&#xff08;Color Histogram&#xff09;&#xff1a; 颜…