消息队列(报文队列):两个进程间通过发送数据块的形式进行通信。一个进程把需要发送的消息通过一个函数发送到消息队列中,另一个进程再从消息队列中读取该消息。
函数:
# include <sys/types.h>
# include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id); //生成下面函数的key.可认为是一个端口号
int msgget(key_t key, int msgflg);//创建消息队列,返回消息队列的 msgid
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);//接收消息队 列中的消息,把接收到的内容写入msgp中。
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);//将msgp中的内容读入消息 队列中。
struct msgstru
{
long mtype; //大于0
char mtext[用户指定大小];
};
msgflg:
1.IPC_CREAT:如果没有就创建,有就打开。
2.IPC_EXCL:本身没多大意义
3.IPC_CREAT|IPC_EXCL:如果没有就创建,有就出错返回,保证每一次创建都是全新的。
特点:
双向通信。
消息队列是随内核持续的。只有在内核重启或显示删除一个消息队列时,才会被真正删除。
消息队列是基于消息的。且消息队列的读取不一定是先入先出。
每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节
每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限(MSGMNI)。
可避免同步和阻塞问题。
comm.h 1 #pragma once 2 #include3 #include 4 #include 5 #include 6 #include 7 #include 8 9 #define _PATH_ "." 10 #define _PROJ_ID_ 0x7777 11 #define _MAX_NUM_ 256 12 #define _SERVER_ 1 13 #define _CLIENT_ 2 14 struct msgstru 15 { 16 long mtype; 17 char mtext[_MAX_NUM_]; 18 }; 19 int creat_msg_queue(); 20 int get_msg_queue(); 21 int send_msg(int msgid,char* text,long type); 22 int recv_msg(int msgid,char* text,long type); 23 int distroy_msg_queue(int msgid); comm.c 1 #include"comm.h" 2 static int comm_msg_queue(int flag) 3 { 4 key_t key = ftok(_PATH_,_PROJ_ID_); 5 if(key == -1) 6 { 7 perror("ftok"); 8 return -1; 9 } 10 int msgid = msgget(key,flag); 11 if(msgid==-1) 12 { 13 perror("msgget"); 14 return -1; 15 } 16 return msgid; 17 } 18 int creat_msg_queue() 19 { 20 return comm_msg_queue(IPC_CREAT|IPC_EXCL|0666); 21 } 22 int get_msg_queue() 23 { 24 return comm_msg_queue(IPC_CREAT); 25 } 26 int send_msg(int msgid,char *text,long type) 27 { 28 struct msgstru msg; 29 msg.mtype = type; 30 strcpy(msg.mtext,text); 31 if(msgsnd(msgid,&msg,sizeof(msg.mtext),0)==-1) 32 { 33 perror("msgsnd"); 34 return -1; 35 } 36 return 0; 37 } 38 int recv_msg(int msgid,char *text,long type) 39 { 40 struct msgstru msg; 41 memset(msg.mtext,'\0',sizeof(msg.mtext)); 42 if(msgrcv(msgid,&msg,sizeof(msg.mtext),type,0)==-1) 43 { 44 perror("msgrcv"); 45 return -1; 46 } 47 strcpy(text,msg.mtext); 48 return 0; 49 50 } 51 int distroy_msg_queue(int msgid) 52 { 53 if(msgctl(msgid,IPC_RMID,NULL)==-1) 54 { 55 perror("msgctl"); 56 return -1; 57 } 58 return 0; 59 } server.c 1 #include"comm.h" 2 int main() 3 { 4 int msgid = creat_msg_queue(); 5 if(msgid == -1) 6 { 7 return -1; 8 } 9 char buf[_MAX_NUM_]; 10 while(1) 11 { 12 memset(buf,'\0',sizeof(buf)); 13 fflush(stdout); 14 printf("please say# "); 15 gets(buf); 16 if(send_msg(msgid,buf,_SERVER_)==-1) 17 { 18 return -1; 19 } 20 if(recv_msg(msgid,buf,_CLIENT_)==-1) 21 { 22 return -1; 23 } 24 printf("client: %s\n",buf); 25 } 26 distroy_msg_queue(msgid); 27 return 0; 28 } client.c 1 #include"comm.h" 2 int main() 3 { 4 int msgid = get_msg_queue(); 5 if(msgid==-1) 6 { 7 return -1; 8 } 9 char buf[_MAX_NUM_]; 10 while(1) 11 { 12 if(recv_msg(msgid,buf,_SERVER_)<0) 13 { 14 return -1; 15 } 16 printf("server: %s\n",buf); 17 fflush(stdout); 18 memset(buf,'\0',sizeof(buf)); 19 printf("please say# "); 20 gets(buf); 21 if(send_msg(msgid,buf,_CLIENT_)==-1) 22 { 23 return -1; 24 } 25 } 26 return 0; 27 } 结果: [fbl@localhost msg_queue]$ ./serverplease say# helloclient: hiplease say# how are you? client: fine,and you?please say# fine[fbl@localhost msg_queue]$ ./clientserver: helloplease say# hiserver: how are you?please say# fine,and you?server: fineplease say#