linux c++進(jìn)程通信之消息隊(duì)列
消息隊(duì)列是一個(gè)存放在內(nèi)核中的消息鏈表,每個(gè)消息隊(duì)列由隊(duì)列標(biāo)識(shí)符標(biāo)識(shí),與管道不同的是消息隊(duì)列是放在內(nèi)核當(dāng)中,只有在內(nèi)核重啟,或者顯式的刪除一個(gè)消息隊(duì)列,該消息隊(duì)列才會(huì)被真正的刪除,以下會(huì)有幾個(gè)操作,
1.創(chuàng)建消息隊(duì)列
#include
#include
key_t ftok(const char* pathname,int proj_id);
根據(jù)傳入的參數(shù)的唯一性,創(chuàng)建一個(gè)消息隊(duì)列
int? msgget(key_t key,int msgflag);
該參數(shù)ley是即為ftok函數(shù)的返回值,mshflag是一個(gè)標(biāo)識(shí)參數(shù)
IPC_CREATE:如果內(nèi)核中不存在于key相等的消息隊(duì)列,則新建一個(gè)消息隊(duì)列
IPC_EXCL和IPC_CREATE一起使用,如果對(duì)應(yīng)鍵值的消息對(duì)流已經(jīng)存在,則出錯(cuò),返回-1
2.寫(xiě)消息隊(duì)列
int msgsnd(int msgid,struct msgbuf* msgp,size_t msgz,int msgflag)
msgid是消息隊(duì)列的標(biāo)識(shí)
msgp是發(fā)送的消息
msgz要發(fā)送的消息的大小
msgflag操作標(biāo)識(shí),當(dāng)他是0的時(shí)候,當(dāng)消息隊(duì)列已曼則,msgsnd則會(huì)阻塞,直到可以寫(xiě)入,如果msgflag是
IPC_NOWAIT的時(shí)候,如果消息隊(duì)列已滿(mǎn)則,立即返回
3.讀消息隊(duì)列
int msgrcv(int msgid,struct msgbuf* msgp,size_t msglen,long msgtyp,int msgflag);
現(xiàn)在源代碼如下
msg_server.c
/* ?*?main.cpp ?* ?*??Created?on:?Jul?18,?2014 ?*??????Author:?john ?*/ #include#include#include#include#include#include#include#include#include#include#include#define?BUF_SIZE?256 #define?PROJ_ID??32 #define?PATH_NAME?"/tmp" #define?SERVER_MSG??1 #define?CLIENT_MSG?2 using?namespace?std; int?main() { ???struct?mymsg ???{ ?????long?msgtype; ?????char?content[256]; ???}msgbuf; ??? ??//?var?define ???int?qid;//消息隊(duì)列標(biāo)識(shí) ????int?msglen;//消息長(zhǎng)度 ???key_t?msgkey; ? ??//獲取鍵值 ??msgkey=ftok(PATH_NAME,PROJ_ID); ??if(msgkey==-1) ???{ ?????cout<<"sorry?key?create?failed:?"<<strerror(errno)<<endl; ?????exit(0);??? ??} ??//獲取消息隊(duì)列 ??cout<<"創(chuàng)建鍵值成功n"; ?? ??qid=msgget(msgkey,IPC_CREAT|0666); ??if(qid==-1) ???{ ??????cout<<"get?msg?quen?failed?"<<strerror(errno)<<endl; ??????exit(0); ???} ??cout<<"獲取消息隊(duì)列成功"<<qid<<"n"; ??//開(kāi)始讀取和寫(xiě)入消息 ??while(1) ??{ ?????cout<>msgbuf.content; ?????if(strncmp(msgbuf.content,"exit",4)==0) ?????{ ???? ?//獲取消息屬性,IPC——RMID從內(nèi)核中刪除qid的消息隊(duì)列 ?????????msgctl(qid,IPC_RMID,NULL); ?????????exit(0); ?????} ?????msgbuf.msgtype=SERVER_MSG; ??????if(?msgsnd(qid,&msgbuf,strlen(msgbuf.content)+1,0)==-1) ?????{ ??????????cout<<"msg?send?failed"<<endl; ??????????exit(1); ?????} ??????cout<<"正在接收客戶(hù)端的消息n"; ?????if(msgrcv(qid,&msgbuf,BUF_SIZE,CLIENT_MSG,0)==-1) ?????{ ?????????cout<<"msg?rcv?failed"<<endl; ?????????exit(0); ?????} ?????cout<<"Client:?"<<msgbuf.content<<endl; ????? ??} }
msg_client.c文件如下:
/* ?*?main.cpp ?* ?*??Created?on:?Jul?18,?2014 ?*??????Author:?john ?*/ #include#include#include#include#include#include#include#include#include#include#include#define?BUF_SIZE?256 #define?PROJ_ID??32 #define?PATH_NAME?"/tmp" #define?SERVER_MSG??1 #define?CLIENT_MSG?2 using?namespace?std; int?main() { ???struct?mymsg ???{ ?????long?msgtype; ?????char?content[256]; ???}msgbuf; ??//?var?define ???int?qid;//消息隊(duì)列標(biāo)識(shí) ????int?msglen;//消息長(zhǎng)度 ???key_t?msgkey; ??//獲取鍵值 ??msgkey=ftok(PATH_NAME,PROJ_ID); ??if(msgkey==-1) ???{ ?????cout<<"sorry?key?create?failed:?"<<strerror(errno)<<endl; ?????exit(0); ??} ??cout<<"獲取鍵值成功n"; ??//獲取消息隊(duì)列 ??qid=msgget(msgkey,IPC_CREAT|0666); ??if(qid==-1) ???{ ??????cout<<"get?msg?quen?failed?"<<strerror(errno)<<endl; ??????exit(0); ???} ??cout<<"獲取消息隊(duì)列成功"<<qid<<"n"; ??//開(kāi)始讀取和寫(xiě)入消息 ??while(1) ??{ ??cout<<"正在接收服務(wù)器給客戶(hù)段的消息n"; ??if(msgrcv(qid,&msgbuf,BUF_SIZE,SERVER_MSG,0)==-1) ??????{ ??????????cout<<"msg?rcv?failed"<<endl; ??????????exit(0); ??????} ??????cout<<"Server:?"<<msgbuf.content<<endl; ?????cout<>msgbuf.content; ?????if(strncmp(msgbuf.content,"exit",4)==0) ?????{ ???? ?//獲取消息屬性,IPC——RMID從內(nèi)核中刪除qid的消息隊(duì)列 ?????????msgctl(qid,IPC_RMID,NULL); ?????????exit(0); ?????} ?????msgbuf.msgtype=CLIENT_MSG; ??????if(?msgsnd(qid,&msgbuf,strlen(msgbuf.content)+1,0)==-1) ?????{ ??????????cout<<"msg?send?failed"<<endl; ??????????exit(1); ?????} ??} }
唯一需要注意的是,在msgrcv的參數(shù)中要寫(xiě)入需要接收的消息的類(lèi)型。