今天,我们来学习一下Unix 消息队列的知识,首先,我们下面举例说明一个Unix 消息队列在 C/S 模式中的应用。 C/S 的一个重要特性就是非对等性, 多个客户机同时向一个服务器提出不同的请求 , 服务器接收并处理客户机的请求后 , 将结果返回给相应的客户机。在这里 , 我们利用两个Unix 消息队列、一个服务进程、若干客户进程来模拟客户 / 服务应用。
由各客户进程将请求信息写入队列 1( 键值 0x16), 消息类型定为 10; 服务进程从队列 1 中读取类型为 10 的消息进行处理 , 并将处理结果放入Unix 消息队列 2( 键值0x17), 将类型置为原客户进程号 , 这样每个客户进程可根据其中的消息类型即进程号再从队列 2 中读出属于自己的结果 。
具体操作时先启动服务进程 (server.c), 创建两个Unix 消息队列 , 键值分别为十六进制 16和 17; 这时再启动若干客户进程 (client.c), 输入一任意字符串 , 这时服务进程则显示客户进程号和原字符串 , 客户进程则回显***个字符被改为 "_" 的处理后的字符串和消息类型( 自身进程号 ) 。如输入字符 "q", 则删除原Unix 消息队列 , 同时退出。源程序清单附后 , 该程序在 UNIX3.2 、 4.2 环境下编译调试通过。
这只是进程通信在机器内部的实现 , 要实现进程在网络机器间的通信还要借助 UNIX 网际系统的套接字来实现。
源程序清单如下 :
- 服务进程 :(server.c)
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/msg.h>
- #define KEY16 (key_t)16
- #define KEY17 (key_t)17
- #include (ctype.h)
- int i,msgid1,msgid2,val;
- char *s
- struct{
- long mtype;
- short stype;
- char mtext[40];
- }buf;
- main()
- {
- cr_q(); /* 创建消息队列 */
- /* 读消息队列 1, 消息队列类型为 10, 等待客户请求 */
- while (msgrcv(msgid1,&buf,42,(long)10, ~ IPC_NOWAIT)>=0)
- {printf("\n text from client is:[%s]",buf.mtext);
- printf ("client pid is <%d> \n",buf.stype);
- process();/* 将处理结果写入消息队列 2*/
- }
- }
- cr_q()
- { msgid1=msgget(KEY16,IPC_CREAT|0666);
- if (msgid1<0) {perror("key16 msgget failed");exit(1);}
- msgid2=msgget(KEY17,IPC_CREAT|0666);
- if (msgid2<0) {perror("key17 msgget failed");exit(1);}
- }
- process()
- {
- bufbuf.mtype=buf.stype;/* 原客户进程号 */
- buf.mtext[0]= ‘ _ ’ ;
- if(msgsnd(msgid2,&buf,42,IPC_NOWAIT)<0)
- {perror("key17 msgsnd failed");exit(1);}
- }
- 客户进程 :(client.c)
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/msg.h>
- define KEY16 (key_t)16
- define KEY17 (key_t)17
- include <ctype.h>
- int msgid1,msgid2;
- struct{
- long mtype;
- short stype;
- char mtext[40];
- }buf;
- char s[41];
- int clean()
- main()
- {
- get_q();/* 取消队列标志符 */
- while (1)
- {
- printf ("\n @ input mtext:");/* 输入字符串 */
- scanf("%s",s);
- if ((strcmp(s,"q")==0)) break;
- strcpy(buf.mtext,s);
- buf.mtype=10; /* 消息类型置为 10*/
- buf.stype=getpid();/* 客户进程号 */
- /* 写消息队列 1, 向服务进程提出请求 */
- if (msgsnd(msgid1,&buf,40, ~ IPC_NOWAIT)<0)
- {perror("key16 msgsnd failed");exit(1);}
- /* 读消息队列 2, 类型为自身进程号 , 接收处理结果 */
- if (msgrcv(msgid2,&buf,42,getpid(), ~ IPC_NOWAIT)<0)
- {perror("key17 msgrcv failed");exit(1);}
- printf("\n the answer from server is:[%s]",buf.mtext);
- printf("mtype is:[%d]",buf.mtype);
- }
- clean();/* 删除消息队列 */
- }
- clean()
- {
- if(msgct1(msgid1,IPC_RMID,(struct msgid*)NULL)<0)
- {perror("key16 msgct1 failed");exit(1);}
- if(msgct1(msgid2,IPC_RMID,(struct msgid*)NULL<0)
- {perror("key17 msgct1 failed");exit(1);}
- printf("msg queue removed\n");
- exit(0);
- }
- get_q()
- {
- msgid1=msgget(KEY16,0);
- if (msgid1<0) {perror("key16 msgget failed");exit(1);}
- msgid2=msgget(KEY17,0);if (msgid2<0) {perror("key17 msgget failed");exit(1);}
- }
关于Unix 消息队列的应用,我们今天就讲解到这里啦,希望大家能够好好的学习,我们会带来更多的Unix 消息队列应用的知识。
【编辑推荐】