消息队列是由内核负责维护管理的链式数据队列,不是根据先后顺序出队,而是根据消息类型进行收发数据。简单来说就是一方发送一串不同消息类型的信息,另一方要根据需要的数据通过不同的消息类型进行提取。
先把消息类型和数据作为数据项放入结构体中,我们先来定义一个头文件以便两边调用:
#pragma once
#define MAXMSG 256
typedef struct msgbuf
{
long type;
char data[MAXMSG];
}Msg;
在写具体的进程双方代码前先来了解一下消息队列的编程模型
进程A | 进程B |
创建消息队列 | 获取消息队列 |
发送消息 | 获取消息 |
获取消息 | 发送消息 |
删除消息队列 | —— |
由上表可以看到,进程A是先发送消息的,所以代码顺序和进程B并不完全相同:
#include <stdio.h>
#include "msg.h"
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc,const char* argv[])
{
//创建消息队列
int msgid=msgget(ftok(".",120),IPC_CREAT|0644);
if(msgget<0)
{
perror("msget");
return -1;
}
//发送消息
Msg msg={};
while(1)
{
msg.type=5;
printf(">>>>>");
scanf("%s",msg.data);
if(msgsnd(msgid,&msg,strlen(msg.data)+1,0))
{
perror("msgsnd");
return -1;
}
if(0==strcmp("quit",msg.data)) break;
//获取消息
if(0==msgrcv(msgid,&msg,MAXMSG,6,0))
{
perror("msgrcv");
break;
}
printf("recv:%s\n",msg.data);
if(0==strcmp("quit",msg.data)) break;
}
printf("通信结束!\n");
//删除消息队列
sleep(1);
if(msgctl(msgid,IPC_RMID,NULL))
{
perror("msgctl");
return -1;
}
return 0;
}
进程B:
#include <stdio.h>
#include "msg.h"
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
int main(int argc,const char* argv[])
{
//获取消息队列
int msgid=msgget(ftok(".",120),IPC_CREAT|0644);
if(msgget<0)
{
perror("msget");
return -1;
}
Msg msg={};
while(1)
{
//获取消息
if(0==msgrcv(msgid,&msg,MAXMSG,5,0))
{
perror("msgrcv");
break;
}
printf("recv:%s\n",msg.data);
if(0==strcmp("quit",msg.data)) break;
//发送消息
msg.type=6;
printf(">>>>>");
scanf("%s",msg.data);
if(msgsnd(msgid,&msg,strlen(msg.data)+1,0))
{
perror("msgsnd");
return -1;
}
if(0==strcmp("quit",msg.data)) break;
}
printf("通信结束!\n");
return 0;
}
over