1.消息隊列什麼?
首先我們在學習數據結構後應該對隊列有了一個確切的理解,那麼在Linux下進程間通信(System V進程間通信)就有這麼一種機制。**消息隊列概念:**也叫報文隊列,其實就是一個消息的鏈表,發送的數據就是帶有類型的數據塊。
2.消息隊列特性:
1.消息隊列是操作系統在內核爲我們創建的一個隊列。
2.數據傳輸:用戶組織一個帶有類型的數據塊,添加到隊列中,其他進程從隊列中讀取特定類型的數據。
3.消息隊列是全雙工(可讀可寫)。關於全雙工對照着半雙工去理解即可。
4.消息隊列的生命週期隨內核。
3.消息隊列的操作步驟:
1.創建/打開消息隊列。
2.發送數據/接收數據
3.釋放消息隊列。
4.消息隊列各步驟函數原型:
- 創建/或打開消息隊列:
int msgget(key_t key, int msgflg);
參數:
key:內核中消息隊列的標識。
msgflg:IPC_CREAT 不存在時創建消息隊列,存在時則打開。
IPC_EXCL與IPC_CREAT同用時,若存在則報錯。
mode權限。
返回值:成功時返回消息隊列句柄;失敗時返回-1;
**注意:**key可以通過函數ftok生成
ftok函數原型:
key_t ftok(const char *pathname, int proj_id);
ftok通過文件的inode節點號與proj_id計算得到一個key值。不過這樣會存在一個缺點:當這個文件被刪除或丟失的時候,這個消息隊列再通過這樣的方式就有可能找不到了。
- 發送消息:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
參數:
msqid:操作句柄msgget返回值。
msgp:結構體masgbuf,用戶自定義,描述msg類型、以及msg正文。
msgsz:發送數據的大小即就是sizeof(mtext)大小。
msgflg:標誌選項。
返回值:成功返回發送的實際字節數,失敗返回:-1。
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
- 接收消息:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);
參數:
msqid:操作句柄msgget返回值。
msgp:結構體masgbuf,用戶自定義,描述msg類型、以及msg正文。
msgsz:期望接收數據的大小。
msgflg:標誌選項。0表示如果接收的數據大於msgsz時,接收數據自動截斷,否則不截斷。
返回值:成功返回發送的實際字節數,失敗返回:-1。
- 消息隊列的釋放:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
參數:
msqid:消息隊列操作句柄。
cmd:操作選項,常用IPC_RMID,用於刪除消息隊列。
buf:用於保存消息隊列的信息,不需要則可以忽略(NULL)。
返回值:成功0,失敗返回-1。
瞭解這些接口及使用方法就可以直接上代碼了
還是server&client通信
server.c:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
#define KEY 0x123456
#define C 1
#define S 2
//存儲消息的結構體
struct msgbuf
{
long mtype;
char mtext[1024];
};
int main()
{
//1.打開/創建消息隊列
int msgid = msgget(KEY,IPC_CREAT|0664);
struct msgbuf buf;
while(1)
{
printf("please wait the client request...\n");
//server端接收數據
msgrcv(msgid,&buf,1024,C,0);
printf("client say:");
fflush(stdout);
printf("%s\n",buf.mtext);
printf("server enter#:");
fflush(stdout);
scanf("%s",&buf.mtext);
//server端發送數據
buf.mtype = S;
msgsnd(msgid,&buf,strlen(buf.mtext),0);
}
//server端刪除消息隊列
msgctl(msgid,IPC_RMID,NULL);
return 0;
}
client.c:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
#define KEY 0x123456
#define C 1
#define S 2
//存儲消息的結構體
struct msgbuf
{
long mtype;
char mtext[1024];
};
int main()
{
//1.打開消息隊列
int msgid = msgget(KEY,IPC_CREAT|0664);
struct msgbuf buf;
while(1)
{
printf("client enter#:");
fflush(stdout);
scanf("%s",&buf.mtext);
//client發送消息
buf.mtype = C;
msgsnd(msgid,&buf,strlen(buf.mtext),0);
printf("please the server respond...\n");
msgrcv(msgid,&buf,1024,S,0);
printf("server say:");
fflush(stdout);
printf("%s\n",buf.mtext);
}
return 0;
}
運行效果展示:
server端:
client端: