一、消息队列
1.消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法。
2.每个数据块都被认为是有一个类型,接受者进程的数据块可以有不同的类型值。
3.消息队列也有管道一样的不足,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限(MSGMNI)。
IPC对象数据结构:
消息队列结构:
二、消息队列函数:
1.msgget函数:
2.mstctl函数:
3.msgsnd函数:
4.msgrcv函数:
注:
三、代码示例
查看与删除消息队列的命令:
(1)查看已创建的消息队列:
ipcs -q
(2)删除已存在的消息队列
ipcrm -q 163840(消息队列的标识符) ( 删除一个消息队列 )
ipcrm -a (删除所有创建了的消息队列)
【comm.h】
#ifndef _COMM_H_
#define _COMM_H_
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
#define PATHNAME "." //"."表示当前目录
#define PROJ_ID 0x6666 //权限设置 6(文件类型)|6(拥有者权限rw-)|6(用户组权限rw-)|6(其他的权限rw-)
#define SERVER_TYPE 1 //TYPE必须设置成一个大于0的数
#define CLIENT_TYPE 2
struct msgbuf{
long mtype;
char mtext[1024];
};
int createMsgQueue(); //创建消息队列
int getMsgQueue(); //代开消息队列
int destoryMsgQueue(int msgid); //销毁一个存在的消息队列
int sendMsg(int msgid,int who,char* msg); //向消息队列发送信息
int recvMsg(int msgid,int recvType,char out[]); //从消息队列中读取数据
#endif
【comm.c】
#include"comm.h"
//success -->(>0) falied -->(-1)
static int commMsgQueue(int flags)
{
key_t _key=ftok(PATHNAME,PROJ_ID); //通过ftok获取一个唯一标识符
if(_key<0)
{
perror("fotk");
return -1;
}
int msgid=msgget(_key,flags);
if(msgid<0)
perror("msgget");
return msgid;
}
int createMsgQueue()
{
return commMsgQueue(IPC_CREAT|IPC_EXCL|0666); //IPC_CREAT如果存在,打开它,如果不存在创建一个;
//IPC_EXCL 如果消息队列不存在,看不见,如果存在失败。
}
int getMsgQueue()
{
return commMsgQueue(IPC_CREAT);
}
int destoryMsgQueue(int msgid)
{
if(msgctl(msgid,IPC_CREAT,NULL)<0)
{
perror("msgctl");
return -1;
}
return 0;
}
int sendMsg(int msgid,int who,char* msg)
{
struct msgbuf buf;
buf.mtype=who;
strcpy(buf.mtext,msg);
if(msgsnd(msgid,(void *)&buf,sizeof(buf.mtext),0)<0)
{
perror("msgsnd");
return -1;
}
return 0;
}
int recvMsg(int msgid,int recvType,char out[])
{
struct msgbuf buf;
if(msgrcv(msgid,(void*)&buf,sizeof(buf.mtext),recvType,0)<0)
{
perror("msgrcv");
return -1;
}
strcpy(out,buf.mtext);
return 0;
}
【server.c】
#include"comm.h"
int main()
{
int msgid=createMsgQueue();
char buf[1024];
while(1)
{
buf[0]=0;
recvMsg(msgid,CLIENT_TYPE,buf); //从消息队列中读取数据
printf("client# %s\n",buf);
printf("Please Enter#");
fflush(stdout);
size_t s=read(0,buf,sizeof(buf));
if(s>0)
{
buf[s-1]=0;
sendMsg(msgid,SERVER_TYPE,buf); //向消息队列发送信息
printf("send done,wait recv...\n");
}
}
destoryMsgQueue(msgid); //销毁一个已存在的消息队列
return 0;
}
【client.c】
#include"comm.h"
int main()
{
int msgid=getMsgQueue();
char buf[1024];
while(1)
{
buf[0]=0;
printf("Please Enter# ");
fflush(stdout);
size_t s=read(0,buf,sizeof(buf));
if(s>0)
{
buf[s-1]=0;
sendMsg(msgid,CLIENT_TYPE,buf);
printf("send done,wait recv...\n");
}
recvMsg(msgid,SERVER_TYPE,buf);
printf("server# %s\n",buf);
}
return 0;
}