首页 > linux进程间通信:消息队列实现双端通信

linux进程间通信:消息队列实现双端通信

双端通信描述

利用消息队列针对发送接受消息的类型唯一性 进行多个客户端之间消息传递,而不需要server端进行消息转发。

同时消息队列的读阻塞和写阻塞特性(消息队列中已经写入数据,如果再不读出来,则无法再次写入)让消息队列的实现过程只能如下:

  • 客户端1的父进程用来处理类型1的消息写,子进程处理类型2的消息读
  • 客户端2的父进程处理类型2的消息写,子进程处理类型1的消息读

实现

客户端1 client1.c

#include
#include 
#include 
#include 
#include 
#include 
#include #define MSG_TYPE1 1
#define MSG_TYPE2 2 struct msgbuf
{ long mtype;char mtext[100];
};int main()
{ //当多用户的时候通过指定文件以及设置id来获取唯一的key标识//key_t key = ftok(".",100);key_t key = 12345; //个人使用的时候可以直接指定key//创建msg_qid的对象int msg_qid = msgget(key, IPC_CREAT | 0666);struct msgbuf msg1,msg2;int ret;char send_buf[100],rcv_buf[100];ret = fork();if ( -1 == ret ) { printf("fork failed! 
");_exit(-1);}//子进程处理消息1的写else if (ret == 0) { while(1) { memset(&msg1, 0 , sizeof(msg1));//初始化消息类型以及消息内容scanf("%s",msg1.mtext);msg1.mtype = MSG_TYPE1;//发送消息到消息标识的msg_qid IPC 对象中/* if( -1 == msgsnd(msg_qid,(void *)&msg1,strlen(msg1.mtext),0)) {printf("send msg1 failed
");_exit(-1);}*/msgsnd(msg_qid,(void *)&msg1,strlen(msg1.mtext),0);}}//父进程处理消息2的读else { while(1) {  memset(&msg2, 0, sizeof(msg2));//获取消息大小为sizeof(msg2.mtext)if (-1 == msgrcv(msg_qid,(void*)&msg2,sizeof(msg2.mtext),MSG_TYPE2,0)){ printf("receive msg2 failed
");_exit(-1);} printf("client1:%s
",msg2.mtext);}}msgctl(msg_qid,IPC_RMID,NULL);return 0;
}

客户端2 client2.c

#include
#include 
#include 
#include 
#include 
#include 
#include #define MSG_TYPE1 1
#define MSG_TYPE2 2 struct msgbuf
{ long mtype;char mtext[100];
};int main()
{ //当多用户的时候通过指定文件以及设置id来获取唯一的key标识//key_t key = ftok(".",100);key_t key = 12345; //个人使用的时候可以直接指定key//创建msg_qid的对象int msg_qid = msgget(key, IPC_CREAT | 0666);struct msgbuf msg1,msg2;int ret;ret = fork();if ( -1 == ret ) { printf("fork failed! 
");_exit(-1);}else if (ret == 0) { while(1) { memset(&msg1, 0 , sizeof(msg1));//初始化消息类型以及消息内容scanf("%s",msg1.mtext);msg1.mtype = MSG_TYPE2;//发送消息到消息标识的msg_qid IPC 对象中/*if( -1 == msgsnd(msg_qid,(void *)&msg1,strlen(msg1.mtext),0)) {printf("send msg1 failed
");_exit(-1);}*/msgsnd(msg_qid,&msg1,100,0);}}else { while(1) {  memset(&msg2, 0, sizeof(msg2));if (-1 == msgrcv(msg_qid,(void*)&msg2,sizeof(msg2.mtext),MSG_TYPE1,0)){ printf("receive msg2 failed
");_exit(-1);} printf("client2:%s
",msg2.mtext);}}msgctl(msg_qid,IPC_RMID,NULL);return 0;
}

编译运行输出如下:

在这里插入图片描述

消息队列相关命令

ipcs -q 查看系统消息队列

ipcrm -q msqid 按照消息标识删除当前用户下的消息队列

ipcmk -Q创建消息队列

消息队列相比于fifo的主要差异

差异:

  • 消息的改变,每个消息都有自己的身份标识
  • 内核提供访问消息结构的接口,并且提供结构来动态修改消息结构

共同点:

消息的接受和发送都是阻塞读和阻塞写,即需要将写的内容读出,否则下次发送会阻塞写

更多相关:

  • 首先对微擎的工作原理做简单描述, 微擎使用规则和模块的机制来处理公众平台的请求数据并返回响应的结果.执行流程描述为: 粉丝用户与公众号码进行对话或交互, 而后公众平台将粉丝用户的请求消息(当前包括: 文本, 图片, 位置, 链接, 事件. 请参阅消息类型)传递给微擎系统, 微擎系统按照消息类型和对应的公众号所设定的规则列表匹配到合适的...

  • 消息队列的使用场景以下介绍消息队列在实际应用常用的使用场景。异步处理、应用解耦、流量削锋和消息通讯四个场景。1】异步处理:场景说明:用户注册后,需要发注册邮件和注册短信。引入消息队列后架构如下:用户的响应时间=注册信息写入数据库的时间,例如50毫秒。发注册邮箱、发注册短信写入消息队列后,直接返回客户端,因写入消息队列的速度很快,基...

  • 下面是我凭记忆想到的几个题目,有需要的同学就拿去吧,我也算做了点善事. 中体骏彩C++笔试题 2013-11-18 1.指针的含义是:B A.名字 B.地址 C.名称 D.符号 2.给出下面的程序输出: #include #include #include ...

  • 文章目录基本介绍编程接口代码实例消息队列的发送和接收消息队列中的消息对象的属性控制 基本介绍 支持不同进程之间以消息(messages)的形式进行数据交换,消息能够拥有自己的标识,且内核使用链表方式进行消息管理。进程之间的通信角色为:发送者和接受者 发送者: a. 获取消息队列的ID(key或者msgid) b. 将数据放入...

  • 关于点云的分割算是我想做的机械臂抓取中十分重要的俄一部分,所以首先学习如果使用点云库处理我用kinect获取的点云的数据,本例程也是我自己慢慢修改程序并结合官方API 的解说实现的,其中有很多细节如果直接更改源程序,可能会因为数据类型,或者头文件等各种原因编译不过,会导致我们比较难得找出其中的错误,首先我们看一下我自己设定的一个场景,...

  • /* 使用正态分布变换进行配准的实验 。其中room_scan1.pcd room_scan2.pcd这些点云包含同一房间360不同视角的扫描数据 */ #include #include #include #include

  • #include #include #include #include ...

  • #include #include #include #include #include #include...

  • #include #include #include #include int main (int argc,...

  • 前言 近期在做on nvme hash引擎相关的事情,对于非全序的数据集的存储需求,相比于我们传统的LSM或者B-tree的数据结构来说 能够减少很多维护全序上的计算/存储资源。当然我们要保证hash场景下的高写入能力,append-only 还是比较友好的选择。 像 Riak的bitcask 基于索引都在内存的hash引擎这种,...

  • 前言 最近在读 MyRocks 存储引擎2020年的论文,因为这个存储引擎是在Rocksdb之上进行封装的,并且作为Facebook 内部MySQL的底层引擎,用来解决Innodb的空间利用率低下 和 压缩效率低下的问题。而且MyRocks 在接入他们UDB 之后成功达成了他们的目标:将以万为单位的服务器集群server个数缩减了一...

  • 参考自:  https://www.cnblogs.com/zeng1994/p/03303c805731afc9aa9c60dbbd32a323.html 1、maven依赖

    springboot redis配置

    1、引入maven依赖 org.springframework.bootspring-boot-starter-data-redis   2、redis连接配置 spring:redis:h...

  • json 键值对增加、删除 obj.key='value'; // obj.key=obj[key]=eval("obj."+key); delete obj.key; vue中新增和删除属性 this.$set(object,key,value) this.$delete( object, key ) 触发视图更新 遍历键值 for...