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

本文详细介绍了Boost库中MessageQueue的使用,包括其作为进程间通信机制的原理、构造函数的用法,以及发送和接收消息的三种模式(阻塞、非阻塞、定时)。还提供了服务端和客户端的示例代码,展示了如何创建、发送和接收消息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前言

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

好的,下面是使用C++Boost创建子进程并使用共享内存的示例代码: ```c++ #include <iostream> #include <boost/interprocess/shared_memory_object.hpp> #include <boost/interprocess/mapped_region.hpp> #include <boost/interprocess/ipc/message_queue.hpp> #include <boost/interprocess/sync/interprocess_mutex.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> #include <boost/interprocess/sync/named_mutex.hpp> #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/ipc/message_queue.hpp> #include <boost/interprocess/streams/bufferstream.hpp> #include <boost/interprocess/streams/vectorstream.hpp> #include <boost/interprocess/ipc/message_queue.hpp> #include <boost/interprocess/sync/interprocess_semaphore.hpp> #include <boost/interprocess/sync/scoped_semaphore.hpp> #include <boost/interprocess/sync/interprocess_condition.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> #include <boost/interprocess/sync/interprocess_recursive_mutex.hpp> #include <boost/process.hpp> using namespace boost::interprocess; using namespace boost::process; int main() { //创建共享内存 shared_memory_object shm_obj(create_only, "my_shm", read_write); shm_obj.truncate(1024); //设置共享内存大小为1024字节 //映射共享内存到当前进程地址空间 mapped_region shm_region(shm_obj, read_write); //获取共享内存的地址 void* shm_addr = shm_region.get_address(); //创建子进程 child c("path/to/my/child/process"); //在子进程中操作共享内存 if (c.id() == 0) { //映射共享内存到子进程地址空间 managed_shared_memory shm(open_only, "my_shm"); //获取共享内存中的vector对象 typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocator; typedef vector<int, ShmemAllocator> MyVector; ShmemAllocator alloc(shm.get_segment_manager()); MyVector* myvector = shm.find_or_construct<MyVector>("MyVector")(alloc); //向vector中添加数据 myvector->push_back(1); myvector->push_back(2); myvector->push_back(3); //等待主进程读取vector中的数据 interprocess_semaphore sem(0); sem.wait(); } else //在主进程中操作共享内存 { //映射共享内存到主进程地址空间 managed_shared_memory shm(open_only, "my_shm"); //获取共享内存中的vector对象 typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocator; typedef vector<int, ShmemAllocator> MyVector; ShmemAllocator alloc(shm.get_segment_manager()); MyVector* myvector = shm.find_or_construct<MyVector>("MyVector")(alloc); //读取vector中的数据并输出 for (auto it = myvector->begin(); it != myvector->end(); ++it) { std::cout << *it << " "; } std::cout << std::endl; //释放共享内存 shared_memory_object::remove("my_shm"); //通知子进程可以退出了 interprocess_semaphore sem(1); sem.post(); } return 0; } ``` 以上代码中使用了Boost中的`shared_memory_object`、`mapped_region`、`managed_shared_memory`、`allocator`、`vector`、`interprocess_semaphore`等类和函数,分别用于创建和操作共享内存、映射共享内存到进程地址空间、在共享内存中创建对象、向共享内存中添加数据、从共享内存中读取数据、等待和通知进程之间的同步操作等。其中,创建子进程使用了Boost.Process中的`child`类和构造函数,可以方便地创建和管理子进程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发如雪-ty

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值