天天看點

消息隊列

消息隊列的基礎知識:

(1).消息隊列是基于消息的,而管道是基于位元組流的,且消息隊列的讀取不一定是先入先出

(2).消息隊列是用連結清單實作的。

2.代碼如下:

輸出結果:

消息隊列

分析:1.client和server都能發送和接受資訊,且能在顯示器上顯示。

    2.當聊天結束,即輸入“quit”時,自動調用destroy()函數,kill掉建立的消息隊列。

    3.缺陷:client和server得一人一句輪流,例如:不能client說了多句,server再說。

3.所涉及函數

(1).建立新消息隊列或取得已存在消息隊列

1).msgget

 原型:int msgget(key_t key, int msgflg);

 參數:key:可以認為是一個端口号,也可以由函數ftok生成。

2).ftok. 函數ftok把一個已存在的路徑名和一個整數辨別得轉換成個key_t值,稱為ipc鍵:

 頭檔案: # include <sys/types.h> 

       # include <sys/ipc.h>

 原型:  key_t ftok(const char *pathname, int proj_id);

 參數:  msgflg:ipc_creat 如果ipc不存在,則建立一個ipc資源,否則打開操作。

           ipc_excl 隻有在共享記憶體不存在的時候,新的共享記憶體才建立,否則就産生錯誤。

    ipc_exel标志本身并沒有太大的意義,但是和ipc_creat标志起使用可以用來保證所得的對象是建立的,而不是打開已有的對象。

   a.如果單獨使用ipc_creat,xxxget()函數傳回一個已經存在的共享記憶體的操作符或傳回一個建立的共享記憶體的辨別符。

   b.如果将ipc_creat和ipc_excl标志一起使用,xxxget()将傳回一個建立的ipc辨別符;或者如果該ipc資源已存在,傳回-1。

(2).向隊列讀/寫消息

 原型:

    1).從隊列中取用消息msgrcv:

         ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);

    2).将資料放到消息隊列中msgsnd:

         int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

 參數:

   msqid:消息隊列的辨別碼

   msgp:指向消息緩沖區的指針,此位置用來暫時存儲發送和接收的消息,是一個使用者可定義的通用結構,形态如下:

struct msgstru

{

    long mtype; //大于0

    char mtext[使用者指定大小];

};

   msgsz:消息的大小。

   msgtyp:從消息隊列内讀取的消息形态。如果值為零,則表示消息隊列中的所有消息都會被讀取。

   msgflg:用來指明核心程式在隊列沒有資料的情況下所應采取的行動。如果msgflg和常數ipc_nowait合用,則在msgsnd()執行時若是消息隊列已滿,則msgsnd()将不會阻塞,而會立即傳回-1,如果執行的是msgrcv(),則在消息隊列呈空時,不做等待馬上傳回-1,并設定錯誤碼為enomsg。當msgflg為0時,msgsnd()及msgrcv()在隊列呈滿或呈空的情形時,采取阻塞等待的處理模式。

 (3).設定消息隊列屬性

 原型:int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );

 參數:msgctl 系統調用對 msgqid 辨別的消息隊列執行 cmd 操作,系統定義了3 種cmd 操作ipc_stat, ipc_set , ipc_rmid

   ipc_stat : 該指令用來擷取消息隊列對應的 msqid_ds 資料結構,并将其儲存到 buf 指定的位址空間。

   ipc_set : 該指令用來設定消息隊列的屬性,要設定的屬性存儲在buf中。  

   ipc_rmid : 從核心中删除 msqid 辨別的消息隊列。

 (4)其他函數

ftok函數:一個已存在的路徑名和一個整數辨別得轉換成一個key_t值,稱為ipc鍵:

  原形:  key_t ftok(const char *pathname, int proj_id);

  傳回值:成功傳回生成的值,失敗傳回-1。

檢視函數可以在編譯時底行模式輸入!man 函數名,或在指令行輸入man 函數名