1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 9 int msg_key = 1234;10 11 struct MsgNode12 {13 long nMsgType;14 char sBuf[256];15 };16 17 int main(int argc,char** argv)18 {19 int nMsgId = 0;20 if((argc == 2) && (strcmp(argv[1],"c") == 0))21 {22 nMsgId = msgget(msg_key,IPC_EXCL);23 if(nMsgId < 0)24 {25 nMsgId = msgget(msg_key,0750|IPC_CREAT);26 if(nMsgId < 0)27 {28 perror("msgget");29 printf("msgget failed\n");30 exit(-1);31 }32 }33 34 for(int i = 0 ;i < 10; ++i)35 {36 MsgNode node;37 node.nMsgType = 1;38 sprintf(node.sBuf,"This is the %d msg from client.\n",i);39 40 if(i == 9)41 {42 strcpy(node.sBuf,"end\n");43 }44 45 printf("%s",node.sBuf);46 47 int ret = msgsnd(nMsgId,&node,sizeof(node.sBuf),IPC_NOWAIT);48 if(ret < 0)49 {50 perror("msgsend");51 printf("msgsend failed");52 exit(-1);53 }54 }55 }56 else57 {58 nMsgId = msgget(msg_key,IPC_EXCL);59 if(nMsgId < 0)60 {61 printf("msgget failed\n");62 exit(-1);63 }64 65 bool flag = true;66 while(flag)67 {68 MsgNode node;69 int ret = msgrcv(nMsgId,&node,sizeof(node.sBuf),1,IPC_NOWAIT);70 if(ret == -1)71 {72 perror("msgrecv");73 printf("msgrecv failed\n");74 exit(-1);75 }76 printf("Receive Msg:%s",node.sBuf);77 //if(strncmp(node.sBuf,"end",3) == 0)78 //{79 // flag = false;80 //};81 }82 83 int ret = msgctl(nMsgId,IPC_RMID,0);84 if( ret == -1)85 {86 printf("msgctl failed\n");87 exit(-1);88 }89 }90 91 return 0;92 }
需要注意的是
int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);
及
int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);
其中 size_t msg_st并不是消息结构体的大小,而是消息的大小。
如代码中定义了结构1 struct MsgNode2 {3 long nMsgType;4 char sBuf[256];5 };
则 size_t msg_st指的是 sizeof(MsgNode.sBuf)即不包括结构中消息类型的长度。
在接受/发送消息时如果不设置为IPC_NOWAIT则发送时如果消息队列已满则阻塞,接收时如果消息队列为空则阻塞。 消息队列跟命名管道有不少的相同之处,通过与命名管道一样,消息队列进行通信的进程可以是不相关的进程,同时它们都是通过发送和接收的方式来传递数据的。在命名管道中,发送数据用write,接收数据用read,则在消息队列中,发送数据用msgsnd,接收数据用msgrcv。而且它们对每个数据都有一个最大长度的限制。
与命名管道相比,消息队列的优势在于,1、消息队列也可以独立于发送和接收进程而存在,从而消除了在同步命名管道的打开和关闭时可能产生的困难。2、同时通过发送消息还可以避免命名管道的同步和阻塞问题,不需要由进程自己来提供同步方法。3、接收程序可以通过消息类型有选择地接收数据,而不是像命名管道中那样,只能默认地接收。
posted on 2016-07-04 14:37 阅读( ...) 评论( ...)