目录
消息队列就是一些消息的队列,用户可以在消息队列中添加信息和读取消息等。这些消息存在于系统内核中,由“队列ID”来进行标识。消息队列可以实现消息的随时查询。
消息队列的实现包括创建或者打开消息队列、添加信息、读取信息和控制消息队列这4种操作。
2、消息队列的使用流程
(1)Key值的获取
#include <sys/types.h>
#include <sys/ipc.h>key_t ftok(const char *pathname, int proj_id);
参数:
pathname:任意路径
proj_id:任意字符返回值:
成功返回key值,失败返回-1
(2)创建、打开消息队列——msgget
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgget(key_t key, int msgflg);
参数:
key:通过ftok创建的key值或者使用IPC_PRIVATE创建私有的消息队列
shmflg:创建共享内存权限,一般填 0664 | IPC_CREAT
返回值:
成功返回消息队列id号,失败返回-1
例:
int msgid = msgget(IPC_PRIVATE, 0664)
(3)发送消息——msgsnd
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数:
msqid:消息队列id
msgp:跟发送消息相关的结构体的首地址
msgsz:消息结构体中正文内容的大小
msgflg:
0——表示以阻塞方式发送内容
IPC_NOWAIT——以非阻塞方式发送内容返回值:
成功返回0,失败返回-1
msgp用法:
#define LEN (sizeof(MSG) - sizeof(long))typedef struct msgbuf
{
long mtype;
char mtext[N];
}MSG;MSG msg;
char buf[N] = {0};
msg.mtype = 100;
fgets(buf, N, stdin);
strcpy(msg.mtest, buf)
msgsnd(msgid, &msg, LEN, 0);
(4)接收消息——msgrcv
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
参数:
msqid:消息队列id
msgp:接收消息相关的结构体的首地址
msgsz:消息结构体中正文内容的大小
msgflg:
0——表示以阻塞方式接收内容
IPC_NOWAIT——以非阻塞方式接收内容
(5)删除消息队列——msgctl
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgctl(int msqid, int cmd, struct msqid_ds *buf);
cmd:操作共享内存的命令
IPC_STAT:获取共享内存的信息,需要用到第三个参数
IPC_SET:设置共享内存信息
IPC_RMID:删除共享内存,第三个参数填空(映射全部取消之后才会删除)
3、代码实现
/*===============================================================
* Copyright (C) 2022 All rights reserved.
*
* 文件名称:in.c
* 创 建 者:QiuCC
* 创建日期:2022年08月11日
* 描 述:兔子向鹰酱发送或者接收消息
*
* 更新日志:
*
================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define N 100
#define typeA 100
#define typeB 200
#define LEN (sizeof(MSG) - sizeof(long))
typedef struct msgbuf
{
long mtype;
char mtext[64];
}MSG;
int main()
{
int ret;//返回值
char buf[N] = {0};//缓冲区
MSG msg;
//获取Key值
key_t key = ftok(".", 'a');
if(key == -1){
perror("key");
exit(-1);
}
//创建消息队列
int msgid;
msgid = msgget(key, 0664 | IPC_CREAT);
if(msgid == -1){
perror("msget");
exit(-1);
}
while(1){
//发送信息
memset(&msg, 0, sizeof(MSG));
memset(buf, 0, N);
msg.mtype = typeA;//文件类型
printf(" 我:\n ");
fgets(buf, N, stdin);
strcpy(msg.mtext, buf);
ret = msgsnd(msgid, &msg, LEN, 0);
if(-1 == ret){
perror("msgsnd");
exit(-1);
}
//发送退出消息
if(strcmp(buf, "我先挂了\n") == 0){
printf("你已经退出聊天\n");
break;
}
//接收信息
memset(&msg, 0, sizeof(MSG));
ret = msgrcv(msgid, &msg, LEN, typeB, 0);
if(ret == -1){
perror("msgrcv");
exit(-1);
}
strcpy(buf, msg.mtext);
printf("鹰酱:\n");
printf("%s", buf);
//接收到对方退出消息
if(strcmp(msg.mtext, "我先挂了\n") == 0){
printf("鹰酱已经挂了\n");
break;
}
}
//删除消息队列
ret = msgctl(msgid, IPC_RMID, NULL);
return 0;
}
/*===============================================================
* Copyright (C) 2022 All rights reserved.
*
* 文件名称:in.c
* 创 建 者:QiuCC
* 创建日期:2022年08月11日
* 描 述:鹰酱向兔子发送或者接收信息
*
* 更新日志:
*
================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define N 100
#define typeA 100
#define typeB 200
#define LEN (sizeof(MSG) - sizeof(long))
typedef struct msgbuf
{
long mtype;
char mtext[64];
}MSG;
int main()
{
int ret;//返回值
char buf[N] = {0};//缓冲区
MSG msg;
//获取Key值
key_t key = ftok(".", 'a');
if(key == -1){
perror("key");
exit(-1);
}
//创建消息队列
int msgid;
msgid = msgget(key, 0664 | IPC_CREAT);
if(msgid == -1){
perror("msget");
exit(-1);
}
while(1){
//接收信息
memset(&msg, 0, sizeof(MSG));
ret = msgrcv(msgid, &msg, LEN, typeA, 0);
if(ret == -1){
perror("msgrcv");
exit(-1);
}
strcpy(buf, msg.mtext);
printf("兔子:\n");
printf("%s", buf);
//接收到对方退出消息
if(strcmp(msg.mtext, "我先挂了\n") == 0){
printf("兔子已经退出聊天\n");
break;
}
//发送信息
memset(&msg, 0, sizeof(MSG));
memset(buf, 0, N);
msg.mtype = typeB;//文件类型
printf(" 我:\n ");
fgets(buf, N, stdin);
strcpy(msg.mtext, buf);
ret = msgsnd(msgid, &msg, LEN, 0);
if(-1 == ret){
perror("msgsnd");
exit(-1);
}
//发送退出消息
if(strcmp(buf, "我先挂了\n") == 0){
printf("你已经退出聊天\n");
break;
}
}
//删除消息队列
ret = msgctl(msgid, IPC_RMID, NULL);
return 0;
}
4、结果展示
从上述结果来看,我们成功的实现了两个进程之间的实时交互!!!
好的,今天的分享就到这啦!
欢迎大家参考、指正!!!