消息队列中的消息结构可以由我们自由定义,具备较强的灵活性。通过消息结构可以共享一个队列,进行消息复用。通常定义一个类似如下的消息结构:
#define MSGMAXDAT 1024
struct mymsg
{
long msg_len; //消息长度
long msg_type; //消息类型
long msg_data[MSGMAXDATA]; //消息内容
};
消息结构相关联的类型字段(msg_type)提供了两个特性:
(1)标识消息,使得多个进程在单个队列上复用消息。
(2)用作优先级字段,允许接收者以不同于先进先出的某个顺序读出各个消息。
例子1:每个应用一个队列,可以在多个客户和单个服务器之间复用消息。使用一个消息队列进行通信,由消息类型标识消息是从客户到服务器,还是服务器到客户。通信模型如下:
按照通信模型编写程序如下:
公共头文件svmsg.h
1 #ifndef SVMSG_H
2 #define SVMSG_H
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <sys/types.h>
8 #include <sys/ipc.h>
9 #include <sys/msg.h>
10 #include <errno.h>
11
12 #define MSG_R 0400 /* read permission */
13 #define MSG_W 0200 /* write permission */
14 #define SVMSG_MODE (MSG_R | MSG_W | MSG_R >>3 | MSG_R >>6)
15 #define MQ_KEY 1234L
16 #define MSGMAX 1024
17 //消息结构
18 struct mymesg
19 {
20 long mesg_len;
21 long mesg_type;
22 char mesg_data[MSGMAX];
23 };
24 #endif
客户端程序sysv_client.c
1 #include "svmsg.h"
2 void client(int ,int);
3
4 int main(int argc,char *argv[])
5 {
6 int msqid;
7 if((msqid = msgget(MQ_KEY,0)) == -1)
8 {
9 perror("megget()");
10 exit(-1);
11 }
12 client(msqid,msqid);
13 exit(0);
14 }
15
16 void client(int readfd,int writefd)
17 {
18 size_t len;
19 ssize_t n;
20 char *ptr;
21 struct mymesg mesg;
22 printf("Send request to server.
");
23 //set pid to message
24 snprintf(mesg.mesg_data,MSGMAX,"%ld",(long)getpid());
25 len = strlen(mesg.mesg_data);
26 mesg.mesg_data[len] = ' '; //blank
27 ptr = mesg.mesg_data+len+1;
28 printf("Enter filename: ");
29 fgets(ptr,MSGMAX-len,stdin);
30 len = strlen(mesg.mesg_data);
31 if(mesg.mesg_data[len-1] == '
')
32 len--;
33 mesg.mesg_len = len;
34 mesg.mesg_type = 1;
35 printf("mesg_data is :%s len=%ld
",mesg.mesg_data, mesg.mesg_len);
36 if(msgsnd(writefd,&(mesg.mesg_type),mesg.mesg_len,0) == -1)
37 {
38 perror("msgsnd() error");
39 exit(-1);
40 }
41 //read from IPC,write to standard output
42 mesg.mesg_type = getpid();
43 while( (n = msgrcv(readfd,&(mesg.mesg_type),MSGMAX,mesg.mesg_type,0))>0)
44 {
45 write(STDOUT_FILENO,mesg.mesg_data,n);
46 putchar('
');
47 }
48 if(n == 0 )
49 {
50 printf("Read file from server is completed.
");
51 }
52 if(n == -1)
53 {
54 perror("msgrcv() error");
55 exit(-1);
56 }
57 }
服务器程序sysv_server.c
1 #include "svmsg.h"
2 void server(int ,int);
3 int main(int argc,char *argv[])
4 {
5 int msqid;
6 if((msqid = msgget(MQ_KEY,SVMSG_MODE | IPC_CREAT)) == -1)
7 {
8 perror("megget()");
9 exit(-1);
10 }
11 server(msqid,msqid);
12 exit(0);
13 }
14
15 void server(int readfd,int writefd)
16 {
17 FILE *fp;
18 char *ptr;
19 pid_t pid;
20 ssize_t n;
21 ssize_t len;
22 struct mymesg mesg;
23 printf("Waiting for client......
");
24 for(; ;)
25 {
26 mesg.mesg_type = 1;
27 if((n = msgrcv(readfd,&(mesg.mesg_type),MSGMAX,mesg.mesg_type,0)) == 0)
28 {
29 printf("pathname missing.
");
30 continue;
31 }
32 mesg.mesg_data[n] = '