歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> Unix教程 >> 講解Unix 消息隊列應用

講解Unix 消息隊列應用

日期:2017/2/27 17:37:51   编辑:Unix教程

今天,我們來學習一下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 網際系統的套接字來實現。

源程序清單如下 :

  1. 服務進程 :(server.c)
  2. #include <stdio.h>
  3. #include <sys/types.h>
  4. #include <sys/ipc.h>
  5. #include <sys/msg.h>
  6. #define KEY16 (key_t)16
  7. #define KEY17 (key_t)17
  8. #include (ctype.h)
  9. int i,msgid1,msgid2,val;
  10. char *s
  11. struct{
  12. long mtype;
  13. short stype;
  14. char mtext[40];
  15. }buf;
  16. main()
  17. {
  18. cr_q(); /* 創建消息隊列 */
  19. /* 讀消息隊列 1, 消息隊列類型為 10, 等待客戶請求 */
  20. while (msgrcv(msgid1,&buf,42,(long)10, ~ IPC_NOWAIT)>=0)
  21. {printf("\n text from client is:[%s]",buf.mtext);
  22. printf ("client pid is <%d> \n",buf.stype);
  23. process();/* 將處理結果寫入消息隊列 2*/
  24. }
  25. }
  26. cr_q()
  27. { msgid1=msgget(KEY16,IPC_CREAT|0666);
  28. if (msgid1<0) {perror("key16 msgget failed");exit(1);}
  29. msgid2=msgget(KEY17,IPC_CREAT|0666);
  30. if (msgid2<0) {perror("key17 msgget failed");exit(1);}
  31. }
  32. process()
  33. {
  34. bufbuf.mtype=buf.stype;/* 原客戶進程號 */
  35. buf.mtext[0]= ‘ _ ’ ;
  36. if(msgsnd(msgid2,&buf,42,IPC_NOWAIT)<0)
  37. {perror("key17 msgsnd failed");exit(1);}
  38. }

  1. 客戶進程 :(client.c)
  2. #include <stdio.h>
  3. #include <sys/types.h>
  4. #include <sys/ipc.h>
  5. #include <sys/msg.h>
  6. define KEY16 (key_t)16
  7. define KEY17 (key_t)17
  8. include <ctype.h>
  9. int msgid1,msgid2;
  10. struct{
  11. long mtype;
  12. short stype;
  13. char mtext[40];
  14. }buf;
  15. char s[41];
  16. int clean()
  17. main()
  18. {
  19. get_q();/* 取消隊列標志符 */
  20. while (1)
  21. {
  22. printf ("\n @ input mtext:");/* 輸入字符串 */
  23. scanf("%s",s);
  24. if ((strcmp(s,"q")==0)) break;
  25. strcpy(buf.mtext,s);
  26. buf.mtype=10; /* 消息類型置為 10*/
  27. buf.stype=getpid();/* 客戶進程號 */
  28. /* 寫消息隊列 1, 向服務進程提出請求 */
  29. if (msgsnd(msgid1,&buf,40, ~ IPC_NOWAIT)<0)
  30. {perror("key16 msgsnd failed");exit(1);}
  31. /* 讀消息隊列 2, 類型為自身進程號 , 接收處理結果 */
  32. if (msgrcv(msgid2,&buf,42,getpid(), ~ IPC_NOWAIT)<0)
  33. {perror("key17 msgrcv failed");exit(1);}
  34. printf("\n the answer from server is:[%s]",buf.mtext);
  35. printf("mtype is:[%d]",buf.mtype);
  36. }
  37. clean();/* 刪除消息隊列 */
  38. }
  39. clean()
  40. {
  41. if(msgct1(msgid1,IPC_RMID,(struct msgid*)NULL)<0)
  42. {perror("key16 msgct1 failed");exit(1);}
  43. if(msgct1(msgid2,IPC_RMID,(struct msgid*)NULL<0)
  44. {perror("key17 msgct1 failed");exit(1);}
  45. printf("msg queue removed\n");
  46. exit(0);
  47. }
  48. get_q()
  49. {
  50. msgid1=msgget(KEY16,0);
  51. if (msgid1<0) {perror("key16 msgget failed");exit(1);}
  52. msgid2=msgget(KEY17,0);if (msgid2<0) {perror("key17 msgget failed");exit(1);}
  53. }

關於Unix 消息隊列的應用,我們今天就講解到這裡啦,希望大家能夠好好的學習,我們會帶來更多的Unix 消息隊列應用的知識。

Copyright © Linux教程網 All Rights Reserved