1. 程式人生 > 其它 >訊息佇列的通訊原理及建立訊息佇列程式設計收發資料

訊息佇列的通訊原理及建立訊息佇列程式設計收發資料

技術標籤:linux

1.訊息佇列,是訊息的連結表,存放在核心中,一個訊息佇列由一個識別符號(即佇列ID)來標識。

2.特點:

  • 訊息佇列是面向記錄的,其中的訊息具有特定的格式以及特定的優先順序
  • 訊息佇列獨立於傳送與接收程序。程序終止時,訊息佇列及其內容並不會被刪除
  • 訊息佇列可以實現訊息的隨機查詢,訊息不一定要以先進先出的次序讀取,也可以按訊息的型別讀取

3.訊息佇列相關api

<1> int msgget(key_t key, int flag);
功能:開啟或建立訊息佇列。

返回值:成功返回佇列ID,失敗返回-1

引數說明:

  • key:訊息佇列的鍵值,多個程序可以通過它訪問同一個訊息佇列,可通過ftok函式來獲取。其中有個特殊值IPC_PRIVATE,用於建立當前程序的私有訊息佇列。在以下兩種情況下,msgget將建立一個新的訊息佇列:1)如果沒有與鍵值key相對應的訊息佇列,並且flag中包含了IPC_CREAT標誌位;2)key引數為IPC_PRIVATE
  • flag:許可權標誌位

*<2> int msgsnd(int msqid, const void ptr, size_t size, int flag);
功能:新增訊息

返回值:成功返回0,失敗返回-1

引數說明:

  • msqid:訊息佇列的佇列ID

  • ptr:指向訊息結構的指標,該訊息結構msgbuf通常如下:

      struct  msgbuf
     {
          long mtype;  // 訊息型別,該結構必須從這個域開始
    
           char mtext[1];  // 訊息正文
     }
    
  • size:訊息正文的位元組數(不包含訊息型別指標變數)

  • flag:1)IPC_NOWAIT:若訊息無法立即傳送(如當前訊息佇列已滿),函式會立即返回0。msgsnd呼叫直到傳送成功為止;2)0:忽略標誌位

*<3> int msgrcv(int msqid, void ptr, size_t size, long type,int flag);
功能:讀取訊息

返回值:成功返回訊息資料的長度,失敗返回-1

引數說明:

  • msqid:訊息佇列的佇列ID
  • ptr:訊息緩衝區,同msgsnd函式的ptr
  • size:訊息正文的位元組數
  • type:有三種情況:1)等於0:接收訊息佇列中第一個訊息;2)大於0:接收訊息佇列中第一個型別為type的訊息;3)小於0:接收訊息佇列中第一個型別值不小於type絕對值且型別值最小的訊息
  • flag:1)MSG_NOERROR:若返回的訊息比size位元組多,則訊息就會截短到size位元組,且不通知訊息傳送程序;2)IPC_NOWAIT:若在訊息佇列中並沒有相應型別的訊息可以接收,則函式立即返回;3)0:msgsnd函式呼叫阻塞直到接收一條相應型別的訊息為止

*<4> int msgctl(int msqid, int cmd, struct msqid_ds buf);
功能:控制訊息佇列

返回值:成功返回0,失敗返回-1

引數說明:

  • msqid:訊息佇列的佇列ID
  • cmd:命令引數,有三個可供選擇:1)IPC_STAT:讀取訊息佇列的資料結構msqid_ds,並將其儲存在buf指定的地址中;2)IPC_SET:設定訊息佇列的資料結構msqid_ds中的ipc_perm域(IPC操作許可權描述結構)值,這個值取自buf引數;3)IPC_RMID:從系統核心中刪除訊息佇列
  • buf:描述訊息佇列的msqid_ds結構型別變數(也可以為NULL)

4.demo:

// 獲取訊息端

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>

struct msgbuf
{
    long mtype;
    
    char mtext[128];
  
};

int main()
{
       struct msgbuf readBuf;

       key_t key;
       key = ftok(".",'z');    //  獲取msgget函式裡的key值
       printf("key = %x\n",key);

       int msgId =  msgget(key,IPC_CREAT|0777);    // 建立訊息佇列,記得要加許可權,成功返回佇列ID
       if(msgId == -1){
                 printf("get Que failed\n");
                      
       }
    
       msgrcv(msgId,&readBuf,sizeof(readBuf.mtext),888,0);  // 讀取訊息
       printf("read from que:%s\n",readBuf.mtext);

       struct msgbuf sendBuf = {988,"thank you for reach"};
       msgsnd(msgId,&sendBuf,strlen(sendBuf.mtext),0);   // 傳送訊息

       msgctl(msgId,IPC_RMID,NULL);       // 刪除訊息佇列

       return 0;

}

// 傳送訊息端

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>

struct msgbuf
{
    long mtype;
    
    char mtext[128];
  
};

int main()
{
       struct msgbuf sendBuf = {888,"this is message from quen"};
       struct msgbuf readBuf;

       key_t key;
       key = ftok(".",'z');
       printf("key = %x\n",key);

       int msgId =  msgget(key,IPC_CREAT|0777);    
       if(msgId == -1){
                 printf("get Que failed\n");
                      
       }
    
       msgsnd(msgId,&sendBuf,strlen(sendBuf.mtext),0);
       printf("send Over\n");

       msgrcv(msgId,&readBuf,sizeof(readBuf.mtext),988,0);
       printf("return from get:%s\n",readBuf.mtext);

       msgctl(msgId,IPC_RMID,NULL);

       return 0;

}

執行結果:
在這裡插入圖片描述