Qt进程通信,不推荐使用QSharedMemory和QLocalSocket,而是推荐ZMQ

ops/2024/9/23 14:29:47/

一、据一位资深的网友说QLocalSocket有问题,共享内存QSharedMemory也有,比如存在多线程问题,不灵活,丢数据等问题都有,而且还占资源。血的教训。后来换成了zmq+protobufZMQ进程内,进程间,机器间(跨电脑)都可以实现通信。

二、推荐使用ZMQ

1、ZeroMQ简称ZMQ

ZMQ(zeromq)被称为史上最快的“消息队列”,它处于会话层之上,应用层之下,使用后台异步线程完成消息的接受和发送,近乎完美的封装了Socket API,大大简化了编程人员的复杂度。其作为消息中间件,在IPC通信领域应用广泛。

 ZeroMQ号称是“史上最快的消息队列”,基于c语言开发的,实时流处理sorm的task之间的通信就是用的zeroMQ。引用官方说法,ZMQ是一个简单好用的传输层,像框架一样的一个socket library,他使得Socket编程更加简单、简洁和性能更高。是一个消息处理队列库,可在多个线程、内核和主机盒之间弹性伸缩。但是,它无疑是极具前景的、并且是人们更加需要的“传统”BSD套接字之上的一层封装。ZMQ让编写高性能网络应用程序极为简单和有趣。确实,它跟RabbitMQ,ActiveMQ之类有着相当本质的区别,ZeroMQ根本就不是一个消息队列服务器,更像是一组底层网络通讯库。

2、ZMQ 4种模型
一对一结对模型(Exclusive-Pair),可以认为是一个TCP Connection,但是TCP Server只能接受一个连接。数据可以双向流动,这点不同于后面的请求回应模型。
请求回应模型(Request-Reply),由Client发起请求,并由Server响应,跟一对一结对模型的区别在于可以有多个Client。
发布订阅模型(Publish-Subscribe),Publish端单向分发数据,且不关心是否把全部信息发送给Subscribe端。如果Publish端开始发布信息时,Subscribe端尚未连接进来,则这些信息会被直接丢弃。Subscribe端只能接收,不能反馈,且在Subscribe端消费速度慢于Publish端的情况下,会在Subscribe端堆积数据。
管道模型(Push-Pull),从 PUSH 端单向的向 PULL 端单向的推送数据流。如果有多个PULL端同时连接到PUSH端,则PUSH端会在内部做一个负载均衡,采用平均分配的算法,将所有消息均衡发布到PULL端上。与发布订阅模型相比,管道模型在没有消费者的情况下,发布的消息不会被消耗掉;在消费者能力不够的情况下,能够提供多消费者并行消费解决方案。该模型主要用于多任务并行。
这4种模型总结出了通用的网络通信模型,在实际中可以根据应用需要,组合其中的2种或多种模型来形成自己的解决方案。

ZMQ可以基于多种传输协议进行通信,包括TCP、UDP、in-process(进程内通信)等。ZMQ提供进程内(inproc://)、进程间(ipc://)、机器间(tcp://)、广播(pgm://)等四种通信协议。

创建一个消息流 

int zmq_bind (void *socket, const char *endpoint);

int zmq_connect (void *socket, const char *endpoint);

bind函数是将socket绑定到本地的端点(endpoint),而connect函数连接到指定的peer端点。

endpoint支持的类型:

void* context = zmq_ctx_new();
void* responder = zmq_socket(context, ZMQ_REP);
int rc = zmq_bind(responder, "inproc://hello");
assert(rc == 0);void* client = zmq_socket(context, ZMQ_REQ);
zmq_connect(client, "inproc://hello");int rc = zmq_bind(socket, "ipc:///tmp/feeds/0");
assert (rc == 0);int rc = zmq_connect(socket, "ipc:///tmp/feeds/0");
assert (rc == 0);void *context = zmq_ctx_new ();
void *responder = zmq_socket (context, ZMQ_REP);
int rc = zmq_bind (responder, "tcp://*:5555");
assert (rc == 0);void *context = zmq_ctx_new ();
void *requester = zmq_socket (context, ZMQ_REQ);
zmq_connect (requester, "tcp://localhost:5555");

3、ZMQ处理进程内通信的原理

其实就是线程之间通过两个队列来交互,对于每个线程来说都是通过其中一个队列发消息给对方,从另一个队列中读取对方发送的消息。zmq所做的就是把pipe绑定到对应的线程上,然后在send和recv的时候通过pipe来发出、获取信息。

4、ZMQ的服务器端和客户端的启动没有固定的先后顺序。‌

ZMQ的设计允许服务器端和客户端在启动时没有固定的先后顺序。这意味着,无论是服务器端还是客户端,都可以首先启动。这种设计提供了更大的灵活性,使得系统的部署和扩展更加方便。

具体来说:

‌服务器端‌可以首先启动,通过调用zmq_bind函数绑定到指定的地址,并开始监听连接。一旦服务器端启动并准备好,它就可以等待客户端的连接请求。
‌客户端‌也可以在服务器端之前启动,通过调用zmq_connect函数尝试连接到服务器。如果服务器尚未启动,客户端的连接请求会在后台异步重试,直到成功连接到服务器。

5、ZMQ编译

ZMQ 是一个高性能, 易使用, 易配置的 Socket 库, 在 linux 里面一句命令能够安装, 但是其 windows 版本安装, 要使用cmake手动编译。

6、官网

https://zeromq.org/

https://github.com/zeromq/libzmq

c语言封装

https://github.com/zeromq/czmq

c++语言封装

https://github.com/zeromq/cppzmq

---

参考文献

Qt网络编程-ZMQ的使用_qt zmq-CSDN博客

【Qt 学习之路】在 Qt 使用 ZeroMQ_qt zeromq-CSDN博客

https://www.cnblogs.com/chenny7/p/6245236.html

 https://zhuanlan.zhihu.com/p/346230632


http://www.ppmy.cn/ops/110171.html

相关文章

杜教筛入门

求 f f f 的前缀和(不要求 f f f 为积) 考虑 h f ∗ g hf*g hf∗g,若 h , g h,g h,g 前缀和都好求,那 f f f 的前缀和 s s s 是好求的 ∑ i 1 n h i ∑ i j ≤ n f i g j \sum_{i1}^n h_i\sum_{ij\le n}f_ig_j i1∑n​h…

灵活连接,无限可能—探索EtherCAT的拓扑艺术

EtherCAT技术具备快速响应和高效率的特点,在工业自动化领域显得至关重要,其灵活的拓扑结构是其核心优势,支持多样化的网络布局,无需交换机或集线器,简化布线,降低成本,提高系统可靠性和灵活性。…

C语言:刷题日志(3)

一.猴子选大王 一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不…

Gin-封装自动路由

O.0 思路一、API二、控制层三、自动路由核心四、分组路由外加中间件使用 思路 由于Java转Go直接使用的goframe框架,然学习Gin时觉得一个接口一个路由太麻烦,于是有了...1、在请求结构体中采用标签的形式,直接给出路由和请求方式 2、在控制层…

【机器学习】自然语言处理中的Transformer模型:深度解析与前沿发展

欢迎来到 破晓的历程的 博客 ⛺️不负时光,不负己✈️ 文章目录 引言Transformer模型概述编码器(Encoder)与解码器(Decoder) 自注意力机制与多头注意力自注意力机制多头注意力机制 位置编码与模型优势位置编码模型优势…

【Android】GreenDao数据库的使用方式

需求 使用GreenDao数据库进行数据的存储。 介绍 GreenDao 是一个轻量级的对象关系映射(ORM)库,用于简化 Android 应用中的数据库操作。它提供了以下主要功能: 简化数据库操作:通过注解定义实体类,Green…

学习之git的团队协作

git团队协作 一 团队内协作 生成SSH公钥私钥 一(跨团队协作)

《黑神话:悟空》怎么备份游戏存档?

某天下午,你在《黑神话:悟空》中努力鏖战,终于击败了一个让你头疼不已的BOSS,正满心欢喜准备迎接新的挑战,突然,电脑死机了。或者更糟,系统崩溃,重启后发现辛苦积累游戏存档没了&…