講解Unix 消息隊列應(yīng)用
今天,我們來學(xué)習(xí)一下Unix 消息隊列的知識,首先,我們下面舉例說明一個Unix 消息隊列在 C/S 模式中的應(yīng)用。 C/S 的一個重要特性就是非對等性, 多個客戶機(jī)同時向一個服務(wù)器提出不同的請求 , 服務(wù)器接收并處理客戶機(jī)的請求后 , 將結(jié)果返回給相應(yīng)的客戶機(jī)。在這里 , 我們利用兩個Unix 消息隊列、一個服務(wù)進(jìn)程、若干客戶進(jìn)程來模擬客戶 / 服務(wù)應(yīng)用。
由各客戶進(jìn)程將請求信息寫入隊列 1( 鍵值 0x16), 消息類型定為 10; 服務(wù)進(jìn)程從隊列 1 中讀取類型為 10 的消息進(jìn)行處理 , 并將處理結(jié)果放入Unix 消息隊列 2( 鍵值0x17), 將類型置為原客戶進(jìn)程號 , 這樣每個客戶進(jìn)程可根據(jù)其中的消息類型即進(jìn)程號再從隊列 2 中讀出屬于自己的結(jié)果 。
具體操作時先啟動服務(wù)進(jìn)程 (server.c), 創(chuàng)建兩個Unix 消息隊列 , 鍵值分別為十六進(jìn)制 16和 17; 這時再啟動若干客戶進(jìn)程 (client.c), 輸入一任意字符串 , 這時服務(wù)進(jìn)程則顯示客戶進(jìn)程號和原字符串 , 客戶進(jìn)程則回顯***個字符被改為 "_" 的處理后的字符串和消息類型( 自身進(jìn)程號 ) 。如輸入字符 "q", 則刪除原Unix 消息隊列 , 同時退出。源程序清單附后 , 該程序在 UNIX3.2 、 4.2 環(huán)境下編譯調(diào)試通過。
這只是進(jìn)程通信在機(jī)器內(nèi)部的實現(xiàn) , 要實現(xiàn)進(jìn)程在網(wǎng)絡(luò)機(jī)器間的通信還要借助 UNIX 網(wǎng)際系統(tǒng)的套接字來實現(xiàn)。
源程序清單如下 :
- 服務(wù)進(jìn)程 :(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(); /* 創(chuàng)建消息隊列 */
- /* 讀消息隊列 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();/* 將處理結(jié)果寫入消息隊列 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;/* 原客戶進(jìn)程號 */
- buf.mtext[0]= ‘ _ ’ ;
- if(msgsnd(msgid2,&buf,42,IPC_NOWAIT)<0)
- {perror("key17 msgsnd failed");exit(1);}
- }
- 客戶進(jìn)程 :(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();/* 取消隊列標(biāo)志符 */
- 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();/* 客戶進(jìn)程號 */
- /* 寫消息隊列 1, 向服務(wù)進(jìn)程提出請求 */
- if (msgsnd(msgid1,&buf,40, ~ IPC_NOWAIT)<0)
- {perror("key16 msgsnd failed");exit(1);}
- /* 讀消息隊列 2, 類型為自身進(jìn)程號 , 接收處理結(jié)果 */
- 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);}
- }
關(guān)于Unix 消息隊列的應(yīng)用,我們今天就講解到這里啦,希望大家能夠好好的學(xué)習(xí),我們會帶來更多的Unix 消息隊列應(yīng)用的知識。
【編輯推薦】