进程间通信——消息队列

(1)消息队列的基本概念:

消息队列可以简单理解为双向链表。消息队列提供了一种从进程向另一个进程发送一个数据的方法,在读或写数据时,要根据数据的大小全部读写。管道是基于字节流的,而消息队列是基于消息。每个数据块都被认为是有一个类型,接收者进程接受的书记可以有不同的类型值。我们可以通过发送消息来避免命名管道的同步和阻塞问题。每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限(MSGMNI)。

(2)消息队列的创建:


key:可以认为是一个端口号,也可以是由函数ftok生成。

msgget:可以有两个值,也可以有一个。当只有一个值时是IPC_CREAT:表示如果这个IPC不存在就需要创建一个,如果存在则只需打开操作。当有两个值时是:IPC_CREAT和IPC_EXCL:表示如果存在IPC时就会报错,如果这个IPC则创建一个IPC。

(3)消息队列的读与写:


msgid:消息队列的标识码

msgp:指向消息缓冲区的指针,用来暂时存储发送和接受的消息,是一个用户可以定义的通用结构。形态为:


msgsz:消息的大小

msgtyp:从消息队列内读取的消息形态,如果值为0表示消息队列中的所有消息都会被读取

msgflg:用来指明核心程序在队列没有数据的情况下采取的行动。如果msgflg和常数IPC_NOWAIT合用,则在msgsnd()执行时如消息队列已满,则msgsnd()将不会阻塞,并且会立即返回-1,如果执行的是msgrcv(),则在消息队列呈空时返回-1,并设定错误码为ENOMSG。当msgflg为0时,msgsnd()以及msgrev()在队列呈满或呈空的情形时,采取阻塞等待的处理方式。

(4)消息队列的属性:


msgctl系统调用对msgqid表示的消息队列执行cmd操作,系统调用了三种cmd操作:IPC_STAT该命令用来获取消息队列对应的msqid_ds数据,并对其保存到buf指定的地址空间。IPC_SET:该命令用来设置消息队列的属性,要设置的属性存储在buf中。IPC_RMID:从内核中删除msqid标识的消息队列。

(5)用消息队列实现进程之间的通信:

comm.h
 #ifndef _COMM_H_
  2 #define _COMM_H_
  3 #include<stdio.h>
  4 #include<sys/types.h>
  5 #include<sys/ipc.h>
  6 #include<sys/sem.h>
  7 #include<string.h>
  8 #include<stdlib.h>
  9 #define PATHNAME "."
 10 #define PROJ_ID 0x6666
 11 #define SERVICE_TYPE 1
 12 #define CLIENT_TYPE 2
 13 
 14 struct msgbuf
 15 {
 16         long mtype;
 17         char mtext[1024];
 18 };
 19 
 20 int CreateMsgQueue();
 21 int GetMsgQueue();
 22 int SendMegQueue(int msgmid,int type,const char *msg);
 23 int RecvMsgQueue(int msgmid,int type,const char *out);
 24 int DestoryMsgQueue(int msgid);
 25 #endif

comm.c 
#include"comm.h"
  2 
  3 static int CommMsgQueue(int flags)
  4 {
  5         key_t _key=ftok(PATHNAME,PROJ_ID);
  6         if (_key<0){
  7                 perror("ftok");
  8                 return -1;
  9         }
 10         int msgid=msgget(_key,flags);
 11         if (msgid<0){
 12                 perror("msgget");
 13                 return -2;
 14         }
 15         return msgid;
 16 }
 17 int CreateMsgQueue()
 18 {
 19         return CommMsgQueue(IPC_CREAT|IPC_EXCL|0666);
 20 }
 21 int GetMsgQueue()
 22 {
 23         return CommMsgQueue(IPC_CREAT);
 24 }
 25 int DestoryMsgQueue(int msgid)
 26 {
 27         if(msgctl(msgid,IPC_RMID,NULL)<0){
 28                 perror("msgctl");
 29                 return -1;
 30         }
 31         return 0;
 32 }
 33 int SendMsgQueue(int msgid,int type,const char *msg)
 34 {
 35         struct msgbuf _mb;
 36         _mb.mtype=type;
 37         strcpy(_mb.mtext,msg);
 38         if(msgsnd(msgid,&_mb,sizeof(_mb.mtext),0)<0){
 39                 perror("msgsnd");
 40                 return -1;
 41         }
 42         return 0;
 43 }
 44 int RecvMsgQueue(int msgid,int type,const char *out)
 45 {
 46         struct msgbuf _mb;
 47         if(msgrcv(msgid,&_mb,sizeof(_mb.mtext),type,0)<0){
 48                 perror("msgrcv");
 49                 return -1;
 50         }
 51         strcpy(_mb.mtext,out);
 52         return 0;
 53 }




server.c
 1 #include"comm.h"
  2 
  3 int main()
  4 {
  5         int msgid=CreateMsgQueue();
  6         char buf[1024];
  7         while(1){
  8                 buf[0]=0;
  9                 RecvMsgQueue(msgid,CLIENT_TYPE,buf);
 10                 printf("client say:%s\n",buf);
 11                 printf("please enter:");
 12                 fflush(stdout);
 13                 ssize_t s=read(0,buf,sizeof(buf)-1);
 14                 if(s>0){
 15                 buf[s-1]=0;
 16                 SendMsgQueue(msgid,SERVICE_TYPE,buf);
 17                 }
 18         }
 19 DestoryMsgQueue(msgid);
 20 return 0;
 21 }

client.c
 #include"comm.h"
  2 
  3 int main()
  4 {
  5         int msgid=CreateMsgQueue();
  6           char buf[1024];
  7           while(1){
  8                   buf[0]=0;
  9                   printf("client enter:");
 10                   fflush(stdout);
 11                   ssize_t s=read(0,buf,sizeof(buf)-1);
 12                   if(s>0){
 13                          buf[s-1]=0;
 14                          SendMsgQueue(msgid,SERVICE_TYPE,buf);
 15                   }
 16                 RecvMsgQueue(msgid,CLIENT_TYPE,buf);
 17                 printf("server say:\n",buf);
 18           }
 19 return 0;
 20 
 21 }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值