c++boost库学习-07-Message Queue

news2024/11/24 13:24:10

一、前言

boost中的消息队列(Message Queue)是进程间通信的一种机制,实际上是其内部也是采用共享内存的方式来达到进程间通信的目的。这也就意味这Message Queue有其局限性:只有处在同一台计算机中的不同进程才能使用消息队列进行通信。消息队列类似于消息列表,每个线程能够往列表里塞消息,也能从列表里读取消息。每一条消息都有三个属性:

  • 1.消息优先级
  • 2.消息长度
  • 3.消息内容

二、消息队列的使用

消息队列的构造函数
消息队列的构造函数有三个分别是:

message_queue_t(create_only_t create_only,
                 const char *name,
                 size_type max_num_msg,
                 size_type max_msg_size,
                 const permissions &perm = permissions());

该构造函数的作用是创建一个消息队列,name用于指定消息队列的名字,max_num_msg指定创建的消息队列最多能有多少条消息同时存在,max_msg_size表示了所有的消息中最大的消息长度,最后一个参数指定了消息队列的权限,默认是0644。值得注意的是,如果已经有一个同名的消息队列存在,那么该构造函数就会抛异常。

message_queue_t(open_or_create_t open_or_create,
                 const char *name,
                 size_type max_num_msg,
                 size_type max_msg_size,
                 const permissions &perm = permissions());

第二个构造函数和的第一个构造函数大同小异,和第一个构造函数的区别是如果已经存在了一个同名消息队列就打开该消息队列,否则则创建新的消息队列。

message_queue_t(open_only_t open_only,
                 const char *name);

第三个构造函数仅仅是打开一个消息队列,如果没有该消息队列,则会抛出异常。

三、发送消息

在消息队列中,不管是发送消息还是接收消息都有三种模式,也分别对应了三个发送或接收的方法。

  • 1:Blocking:阻塞,对于发送方来说,如果消息队列满了,则发送消息会被阻塞,直到消息队列有多余的位置来存放此条消息。而对于接收方接收数据时,如果消息队列为空,也会阻塞直到消息队列中有数据可读。
  • 2:Try,非阻塞的方式,不管消息队列是空还是满都会立刻返回false。
  • 3:Timed,阻塞的方式,和第一种不同的时,他会阻塞一定的时间,如果时间到了队列还是空或满的,则会返回false。

对于发送方,其三种发送的方式如下:

void send(const void *buffer,     size_type buffer_size,
              unsigned int priority);
              
bool try_send(const void *buffer,  size_type buffer_size,
               unsigned int priority);

bool timed_send(const void *buffer, size_type buffer_size,
                 unsigned int priority,  const boost::posix_time::ptime& abs_time);

如上,send是阻塞的方法,try_send是非阻塞的方法,timed_send是有时间限制阻塞的方法。
参数buffer表示是消息的缓冲区,buffer_size表示buffer的大小,priority表示消息的优先级,abs_time则表示等待的时间。
但其实不管是哪种方法,都不过是对do_send方法的一层封装。

四、接收消息

接收消息同样也有三种方法,阻塞,非阻塞和有时间限制的阻塞三种。方法如下:

inline void message_queue_t<VoidPointer>::receive(void *buffer,        size_type buffer_size,
                        size_type &recvd_size,   unsigned int &priority)
{  this->do_receive(blocking, buffer, buffer_size, recvd_size, priority, ptime()); }

template<class VoidPointer>
inline bool
   message_queue_t<VoidPointer>::try_receive(void *buffer,              size_type buffer_size,
                              size_type &recvd_size,   unsigned int &priority)
{  return this->do_receive(non_blocking, buffer, buffer_size, recvd_size, priority, ptime()); }

template<class VoidPointer>
inline bool
   message_queue_t<VoidPointer>::timed_receive(void *buffer,            size_type buffer_size,
                                size_type &recvd_size,   unsigned int &priority,
                                const boost::posix_time::ptime &abs_time)
{
   if(abs_time == boost::posix_time::pos_infin){
      this->receive(buffer, buffer_size, recvd_size, priority);
      return true;
   }
   return this->do_receive(timed, buffer, buffer_size, recvd_size, priority, abs_time);
}

与发送方法类似,这三种方法也不过是对do_receive方法的一层封装。
do_receive函数原型如下:

template<class VoidPointer>
inline bool
   message_queue_t<VoidPointer>::do_receive(block_t block,
                          void *buffer,            size_type buffer_size,
                          size_type &recvd_size,   unsigned int &priority,
                          const boost::posix_time::ptime &abs_time)

第一个参数block则是表示三种模式之一,buffer表示等待接收数据的缓冲区,buffer_size表示缓冲区的大小,recvd_size表示实际接收到的字节数,priority表示消息优先级,abs_time表示的是阻塞的最大时间。
do_receive的处理逻辑和do_send的处理逻辑大同小异。第一步也是对buffer_size与max_msg_size进行比较,如果buffer_size小于max_msg_size则会抛异常,这是为了保证接收方的buffer要比消息队列中最大消息长度都要大,以满足消息的正常接收。

if (buffer_size < p_hdr->m_max_msg_size) {
      throw interprocess_exception(size_error);
   }

第二步是对消息队列为空时的处理,和发送方对消息队列为满时的处理一致,这里不再赘述。
第三步拷贝数据也是简单的调用memcpy拷贝内存数据。

五、demo

服务端:

#include <boost/interprocess/ipc/message_queue.hpp>
#include <iostream>
#include <vector>

using namespace boost::interprocess;

int main()
{
	try {
		//Erase previous message queue
		message_queue::remove("message_queue");

		//Create a message_queue.
		message_queue mq
		(create_only               //only create
			, "message_queue"           //name
			, 100                       //max message number
			, sizeof(int)               //max message size
		);

		//Send 100 numbers
		for (int i = 0; i < 100; ++i) {
			mq.send(&i, sizeof(i), 0);
		}


	}
	catch (interprocess_exception & ex) {
		std::cout << ex.what() << std::endl;
		return 1;
	}
	system("pause");
	return 0;
}

客户端:

#include <boost/interprocess/ipc/message_queue.hpp>
#include <iostream>
#include <vector>

using namespace boost::interprocess;

int main()
{
	try {
		//Open a message queue.
		message_queue mq
		(open_only        //only create
			, "message_queue"  //name
		);

		unsigned int priority;
		message_queue::size_type recvd_size;

		//Receive 100 numbers
		for (int i = 0; i < 200; ++i)
		{
			int number;
			mq.receive(&number, sizeof(number), recvd_size, priority);
			printf("I:%d Rec:%d\n", i, number);
			if (number != i || recvd_size != sizeof(number))
				return 1;
		}
	}
	catch (interprocess_exception & ex) {
		message_queue::remove("message_queue");
		std::cout << ex.what() << std::endl;
		return 1;
	}
	message_queue::remove("message_queue");
	system("pause");
	return 0;
}

结果:
在这里插入图片描述

————————————————
参考链接:https://blog.csdn.net/weixin_43055404/article/details/111885041

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

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

相关文章

在原有机械硬盘的基础上集装固态硬盘并装操作系统

1、加装固态硬盘 我的电脑出场自带的是机械硬盘&#xff08;即右边那个白色长方形&#xff0c;上面有类似于锡纸一样的东西&#xff09;&#xff0c;左边的这个光滑的正方形里面是内存条&#xff0c;可以拆开这个光滑的盖进行安装&#xff0c;而我们的固态硬盘装在左下角这个长…

性能测试——性能统计工具

性能统计工具 一、io监控命令1、io监控命令iostat2、io指标监控命令df 二、cpu监控命令1、cpu指标监控命令uptime2、cpu指标监控命令 cat /proc/cpuinfo3、cpu 指标监控命令 mpstat4、cpu指标监控命令 sar 三、mem指标监控命令1、mem指标监控命令 cat /proc/meminfo2、mem指标监…

KVM虚拟化(二)

文章目录 4.7 kvm虚拟机克隆4.7.1 完整克隆4.7.2 链接克隆 4.8 kvm虚拟机的桥接网络4.8.1 创建桥接网卡4.8.2 新虚拟机使用桥接模式4.8.3 将已有虚拟机网络修改为桥接模式 4.9 热添加技术4.9.1 kvm热添加硬盘4.9.2 kvm虚拟机在线热添加网卡4.9.3 kvm虚拟机在线热添加内存4.9.4 …

自动化测试技术解析:Appium、Sikuli与MonkeyTalk

目录 前言&#xff1a; 一、Appium自动化测试框架 它的优点是&#xff1a; 二、Sikuli自动化测试工具 它的优点是&#xff1a; 三、MonkeyTalk自动化测试工具 它的优点是&#xff1a; 四、代码样例 总结&#xff1a; 前言&#xff1a; 随着移动应用的普及&#xff0c;…

手把手教你通过PaddleHub快速实现输入中/英文本生成图像(Stable Diffusion)

近来&#xff0c;基于Diffusion的文图生成模型比较火&#xff0c;用户输入一句话&#xff0c;模型就可以生成一副对应的图像&#xff0c;还是很有意思的。本文记录了通过PaddleHub快速实现上述任务的过程&#xff0c;以供参考。 1、安装PaddlePaddle PaddleHub底层依赖于百度…

ChatGPT工作提效之生成开发需求和报价单并转为Excel格式

ChatGPT工作提效之生成开发需求和报价单并转为Excel格式 一、提出需求如何撰写百度地图标注开发的需求文档 二、针对性地连续提问推荐下一下百度地图标注文档的详细需求列表如何撰写百度地图标注开发的技术规范如何确定百度地图标注开发后的部署计划... 三、生成报价单四、运营…

【2023 · CANN训练营第一季】进阶班 应用开发深入讲解→模型推理

1 模型离线推理 各步要解析如下: Host&Device内存管理与数据传输: Host&Device上的内存申请与释放&#xff0c;内存间的相互拷贝;模型加载:将离线的om文件加载到Device上;在样例的资源初始化模块中进行。模型输入输出准备∶根据禹线om的输入输出&#xff0c;在Device…

微信小程序富文本组件mp-html

功能介绍 支持在多个主流的小程序平台和 uni-app 中使用支持丰富的标签&#xff08;包括 table、video、svg 等&#xff09;支持丰富的事件效果&#xff08;自动预览图片、链接处理等&#xff09;支持设置占位图&#xff08;加载中、出错时、预览时&#xff09;支持锚点跳转、…

【Linux】在Linux操作系统下对于权限的理解

目录 ❤️前言 正文 Linux下的不同用户 Linux的权限管理 文件访问者的分类 文件类型和访问权限 文件访问权限的修改方法 默认权限 目录权限 粘滞位 &#x1f340;结语 ❤️前言 大家好&#xff01;今天这篇文章主要是关于Linux操作系统下对于各种权限的理解问题&#…

AI人工智能预处理数据的方法和技术有哪些?

AI人工智能 预处理数据 在人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;领域中&#xff0c;数据预处理是非常重要的一环。它是在将数据输入到模型之前对数据进行处理和清洗的过程。数据预处理可以提高模型的准确性、可靠性和可解释性。 本文将…

Springboot +spring security,基于多种方式配置登录用户:memory、jdbc、MyBatis

一.简介 前面章节所有的用户信息(用户名和密码)都是基于配置文件配置的&#xff0c;这篇文章学习基于多种方式配置登录用户&#xff0c;比如&#xff1a; memory&#xff08;内存&#xff09;jdbcMyBatis 二.创建项目 如何创建一个SpringSecurity项目&#xff0c;前面文章已…

Python入门【序列、列表简介、列表的创建 、列表元素的增加、列表元素的删除 】(四)-全面详解(学习总结---从入门到深化)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小王&#xff0c;CSDN博客博主,Python小白 &#x1f4d5;系列专栏&#xff1a;python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 &#x1f4e7;如果文章知识点有错误…

微服务架构初探

大家好&#xff0c;我是易安&#xff01;我们今天来谈一谈微服务架构的前世今生。 我们先来看看维基百科是如何定义微服务的。微服务的概念最早是在2014年由Martin Fowler和James Lewis共同提出&#xff0c;他们定义了微服务是由单一应用程序构成的小服务&#xff0c;拥有自己的…

chatgpt赋能Python-pythonfalse

PythonFalse&#xff1a; Python中的False值 在Python编程语言中&#xff0c;布尔(Boolean)是一种基本数据类型&#xff0c;它只有两个值&#xff1a;True和False。这篇文章将讨论Python中的False值&#xff0c;并提供有关如何使用它的指南。 什么是PythonFalse PythonFalse…

chatgpt赋能Python-pythongil

Python GIL&#xff08;全局解释器锁&#xff09;介绍 Python GIL 是全局解释器锁&#xff08;Global Interpreter Lock&#xff09;的简称&#xff0c;它是 Python 解释器中的一个重要概念。GIL 的作用是确保任何时间只有一个线程在执行 Python 指令&#xff0c;以防止多个线…

jsonmodels.model.base

欢迎来到猫子酱的学习之旅 jsonmodels.model创建模型用法验证 validate()验证器 Validators自定义验证器&#xff08;**&#xff09;默认值转换为Python结构&#xff08;和JSON&#xff09;为您的模型创建JSON模式(***) &#xff08;结合Draft7Validator&#xff09;结构和对象…

蓝桥杯单片机串口通信学习提升笔记

今日得以继续蓝桥杯国赛备赛之旅&#xff1a; 有道是 “不知何事萦怀抱&#xff0c;醒也无聊&#xff0c;醉也无聊&#xff0c;梦也何曾到谢桥。” 那我们该如何 让这位诗人纳兰 “再听乐府曲 &#xff0c;畅解相思苦”呢&#xff1f; 那就建立起串口通信吧&#xff01; 我…

论文阅读_音频表示_W2V-BERT

信息 number headings: auto, first-level 2, max 4, _.1.1 name_en: w2v-BERT: Combining Contrastive Learning and Masked Language Modeling for Self-Supervised Speech Pre-Training name_ch: W2V-BERT&#xff1a;结合对比学习和Mask语言建模进行自监督语音预训练 pape…

Redis实现全局唯一Id

Redis实现全局唯一Id 全局唯一Id简介二、Redis实现全局唯一Id实践2.1添加RedisIdWorker配置类2.2测试类 全局唯一Id简介 系统当中有些场景如果使用数据库自增ID就存在一些问题&#xff1a; id的规律性太明显受单表数据量的限制 场景分析&#xff1a;如果我们的id具有太明显的…

基于UDP和TCP套接字实现简单的回显客户端服务器程序

目录 1. 套接字 2. 基于UDP 套接字实现的简单客户端 服务器程序 3. 基于TCP套接字实现的简单客户端 服务器程序 1. 套接字 之前我们有分享到协议分层这个概念,其中就讲到上层协议调用下层协议,下层协议给上层协议提供支持,这里支持指的是就是socket套接字,它是操作系统给应用…