消息队列(报文队列):两个进程间通过发送数据块的形式进行通信。一个进程把需要发送的消息通过一个函数发送到消息队列中,另一个进程再从消息队列中读取该消息。
函数:
# 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 #include<stdio.h>
3 #include<sys/types.h>
4 #include<sys/ipc.h>
5 #include<sys/msg.h>
6 #include<stdlib.h>
7 #include<string.h>
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]$ ./server
please say# hello
client: hi
please say# how are you?
client: fine,and you?
please say# fine
[fbl@localhost msg_queue]$ ./client
server: hello
please say# hi
server: how are you?
please say# fine,and you?
server: fine
please say#