消息队列概念
消息队列提供了一个进程将一个数据块发送到另一个进程的方法。
相比于管道的同步与阻塞,消息队列很好的解决了这个问题
管道通信是基于字节流的,然而消息队列发送的是一个数据结构,即IPC对象
消息队列的总字节数是有上限的,消息队列的总数也是有一定上限的
IPC对象的内容(消息队列,信号量和共享内存共同的IPC对象)
消息队列的结构
与消息队列有关的函数
头文件
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
消息队列的创建
函数
int msgget(int key, int flags)
key是 int ftok(const char* pathname, int PROJ_ID)的返回值,其中pathname是路径名,PROJ_ID是工程号
flags有两个参数,分别是IPC_CREAT和IPC_EXCL
IPC_CREAT 单独使用时,创建一个IPC资源,如果资源已经存在,则获得当前存在的资源
IPC_EXCL 只有在共享内存不存在时进行创建,如果存在则会报错
当IPC_CREAT和IPC_EXCL共同使用时,返回一个新建的IPC标识符,如果IPC资源已经存在则返回-1,从而保证对象是新建产生的
消息队列的销毁
函数
int msgctl(int msg_id, int cmd, struct msqid_ds* buf)
msgctl系统调用对msgqid标识的消息队列执行cmd操作
系统定义的三种cmd操作:IPC_STAT,IPC_SET,IPC_RMID
IPC_STAT:获取msqid_ds数据结构,并保存到buf所指向的地址空间
IPC_SET:设置消息队列的属性,并存储到buf中
IPC_RMID:从系统中删除msgqid标识的消息队列
消息队列的发送
函数
int msgsnd(int msqid,const void* msgp,size_t msgsz,int msgflg)
msqid:消息队列的表识码
msgp:指向消息缓冲区的指针,来暂时存储发送和接受的消息,是一个用户自定义的数据结构
struct msgstru
{
long mType;
char mText[大小可变];
};
msgsz:消息队列的大小
msgflg:当msgflg为0时,msgsnd()或msgrcv()呈现满或者空的情形时,采取阻塞等待处理的模式
消息队列的接受
函数
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
msgtyp:表示从消息队列内读取的消息形态。如果值为零,则表示消息队列中的所有消息都 会被读取。
Linux下查看系统中的IPC信息
ipcs -q
Linux下删除系统中的IPC信息
ipcrm -q
代码实现消息队列
comm.h
#include"comm.h"
int main()
{
int msqid = CreatMsgQueue();
if(msqid < 0)
{
perror("CreatMsgQueue");
return -1;
}
char buf[1024];
while(1)
{
buf[0] = 0;
if(RcvMsg(msqid,CLIENT_TYPE,buf) == -1)
{
perror("RevMsg");
return -2;
}
printf("Client# %s",buf);
printf("Server Enter#");
fflush(stdout);
ssize_t s = read (0,buf,sizeof(buf)-1);
if(s < 0)
{
perror("read");
return -3;
}
buf[s] = 0;
if(SndMsg(msqid,SERVER_TYPE,buf) == -1)
{
perror("SndMsg");
return -4;
}
}
DestoryMsgQueue(msqid);
return 0;
}
comm.c
#include"comm.h"
int main()
{
int msqid = CreatMsgQueue();
if(msqid < 0)
{
perror("CreatMsgQueue");
return -1;
}
char buf[1024];
while(1)
{
buf[0] = 0;
if(RcvMsg(msqid,CLIENT_TYPE,buf) == -1)
{
perror("RevMsg");
return -2;
}
printf("Client# %s",buf);
printf("Server Enter#");
fflush(stdout);
ssize_t s = read (0,buf,sizeof(buf)-1);
if(s < 0)
{
perror("read");
return -3;
}
buf[s] = 0;
if(SndMsg(msqid,SERVER_TYPE,buf) == -1)
{
perror("SndMsg");
return -4;
}
}
DestoryMsgQueue(msqid);
return 0;
}
client.c
#include"comm.h"
int main()
{
int msqid = GetMsgQueue();
if(msqid < 0)
{
perror("GetMsgQueue");
return -1;
}
char buf[1024];
while(1)
{
buf[0] = 0;
printf("Client Enter# ");
fflush(stdout);
ssize_t s = read(0,buf,sizeof(buf)-1);
if(s < 0)
{
perror("read");
return -2;
}
buf[s] = 0;
if(SndMsg(msqid,CLIENT_TYPE,buf)<0)
{
perror("SndMsg");
return -3;
}
if(RcvMsg(msqid,SERVER_TYPE,buf)<0)
{
perror("RcvMsg");
return -4;
}
printf("Server echo# %s",buf);
}
return 0;
}
server.c
#include"comm.h"
int main()
{
int msqid = CreatMsgQueue();
if(msqid < 0)
{
perror("CreatMsgQueue");
return -1;
}
char buf[1024];
while(1)
{
buf[0] = 0;
if(RcvMsg(msqid,CLIENT_TYPE,buf) == -1)
{
perror("RevMsg");
return -2;
}
printf("Client# %s",buf);
printf("Server Enter#");
fflush(stdout);
ssize_t s = read (0,buf,sizeof(buf)-1);
if(s < 0)
{
perror("read");
return -3;
}
buf[s] = 0;
if(SndMsg(msqid,SERVER_TYPE,buf) == -1)
{
perror("SndMsg");
return -4;
}
}
DestoryMsgQueue(msqid);
return 0;
}
makefile
#include"comm.h"
int main()
{
int msqid = CreatMsgQueue();
if(msqid < 0)
{
perror("CreatMsgQueue");
return -1;
}
char buf[1024];
while(1)
{
buf[0] = 0;
if(RcvMsg(msqid,CLIENT_TYPE,buf) == -1)
{
perror("RevMsg");
return -2;
}
printf("Client# %s",buf);
printf("Server Enter#");
fflush(stdout);
ssize_t s = read (0,buf,sizeof(buf)-1);
if(s < 0)
{
perror("read");
return -3;
}
buf[s] = 0;
if(SndMsg(msqid,SERVER_TYPE,buf) == -1)
{
perror("SndMsg");
return -4;
}
}
DestoryMsgQueue(msqid);
return 0;
}
运行结果