笔记六:进程间的通信(IPC通信之消息队列)

IPC通信之消息队列
“消息”是在两台计算机间传送的数据单位。消息可以非常简单,例如只包含文本字符串;也可以更复杂,可能包含嵌入对象 。消息被发送到队列中。“消息队列”是在消息的传输过程中保存消息的容器。消息队列管理器在将消息从它的源中继到它的目标时充当中间人。队列的主要目的是提供路由并保证消息的传递;如果发送消息时接收者不可用,消息队列会保留消息,直到可以成功地传递它。
链式队列
   
M sqid_ds   维护消息队列的结构体,队列的第一个消息指针msg_first,最后一个消息指针msg_last
消息中有一个成员指针next
管道属于顺序队列,消息队列属于链式队列;
每一个消息中包含有哪些内容:
   Data    数据
   Length  数据的长度
   Type    数据的类型。
  例如:
      1----voltage data
      2----电流数据
      3----有功功率
  消息的接收端可以根据消息的类型来接收。
  
文件I/O
消息队列
open
msg_get               
read
msgrcv
write
msgsnd
close
msgctrl
(1) msgget(打开消息队列)
所需头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
函数原型
int msgget(key_t key, int flag);
函数参数
key:和消息队列关联的key
flag:消息队列的访问权限
函数返回值
成功:消息队列ID
出错:-1
  属于链式队列,所以无需队列的大小
(2) msgsnd(消息队列的发送)相当于队列的插入== write
所需头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
函数原型
int msgsnd(int msqid, const void *msgp, size_t size, int flag);
函数参数
msqid:消息队列的ID
msgp:指向消息的指针。常用消息结构msgbuf如下:
struct msgbuf
{
    long mtype;          //消息类型
      char mtext[N]      //消息正文
 } 
size:发送的消息正文的字节数
flag
IPC_NOWAIT 消息没有发送完成函数也会立即返回。
0:直到发送完成函数才返回
函数返回值
成功:0
出错:-1  
    参数:
         第一个参数:告诉内核写哪一个消息队列;
         第二个参数:缓存(写什么内容)消息结构体,一定要包含消息的内型;
         第三个参数:想写多少个,想写的正文的字节数;
         第四个参数:阻塞方式;
#include "sys/ipc.h"
#include "sys/msg.h"
#include "sys/types.h"
#include "stdio.h"
struct mybuf
{
  long mytype;
  char sendbuf[128];
};
int main()
{
  int key;
  int msgid;
  struct mybuf  wrbuf,rdbuf;
  key=ftok("./a.c",'a');
  if(key < 0)
  {
      printf("creat key failure\n");
      return -1;
  }
  msgid=msgget(key,IPC_CREAT | 0777);
  if(msgid < 0)
  {
      printf("creat message queue failure\n");
      return -2;
  }
  wrbuf.mytype=10;// voltage data
  printf("please input data:\n");
  fgets(wrbuf.sendbuf,128,stdin);
 
  msgsnd(msgid,(void *)&wrbuf,128,0);
  system("ipcs -q");
  //read
  msgrcv(msgid,(void *)&rdbuf,128,11,0);
  printf("%s",rdbuf.sendbuf);
  system("ipcs -q");
  msgctl(msgid,IPC_RMID,NULL);
  return 0;
}
  
(3)msgrcv(消息队列的接收)相当于队列的删除==read       
所需头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
函数原型
int msgrcv(int msgid,  void* msgp,  size_t  size,  long msgtype,  int  flag);
函数参数
msqid:消息队列的ID
msgp:接收消息的缓冲区
size:要接收的消息的字节数
msgtype
 0:接收消息队列中第一个消息。
大于0:接收消息队列中第一个类型为msgtyp的消息.
小于0:接收消息队列中类型值不大于msgtyp的绝对值且类型值又最小的消息。
flag
0:若无消息函数会一直阻塞
IPC_NOWAIT:若没有消息,进程会立即返回ENOMSG
函数返回值
成功:接收到的消息的长度
出错:-1
  
 消息队列中数据读后,数据也不存在了
(4)msgctl
所需头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
函数原型
int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );
函数参数
msqid:消息队列的队列ID
 
cmd
IPC_STAT:读取消息队列的属性,并将其保存在buf指向的缓冲区中。
 
 
IPC_SET:设置消息队列的属性。这个值取自buf参数。
 
 
IPC_RMID:从系统中删除消息队列。
 
buf:消息队列缓冲区
函数返回值
成功:0
 
出错:-1
例子:
server.c 端
#include "sys/ipc.h"
#include "sys/msg.h"
#include "sys/types.h"
#include "stdio.h"
#include "string.h"
struct mybuf
{
  long mytype;
  char sendbuf[128];
};
int main()
{
  int key;
  int msgid;
  int pid;
  struct mybuf  wrbuf,rdbuf;
  key=ftok("./a.c",'a');
  if(key < 0)
  {
      printf("creat key failure\n");
      return -1;
  }
  msgid=msgget(key,IPC_CREAT | 0777);
  if(msgid < 0)
  {
      printf("creat message queue failure\n");
      return -2;
  }
  pid=fork();
  if(pid < 0)
        return -3;
  if(pid > 0)//write type=10
  {
      wrbuf.mytype=10;// voltage data
      while(1)
     {
     memset(wrbuf.sendbuf,0,128);
     printf("please input data:\n");
     fgets(wrbuf.sendbuf,128,stdin);
     msgsnd(msgid,(void *)&wrbuf,128,0);
      }
  }
 
  //read
  if(pid == 0)  //read type=11
  {
      while(1)
      {
      memset(rdbuf.sendbuf,0,128);
      msgrcv(msgid,(void *)&rdbuf,128,11,0);
      printf("%s",rdbuf.sendbuf);
      }
  }
  msgctl(msgid,IPC_RMID,NULL);
  return 0;
}
client.c 端
#include "sys/ipc.h"
#include "sys/msg.h"
#include "sys/types.h"
#include "stdio.h"
#include "string.h"
struct mybuf
{
  long mytype;
  char sendbuf[128];
};
int main()
{
  int key;
  int msgid;
  int pid;
  struct mybuf  wrbuf,rdbuf;
  key=ftok("./a.c",'a');
  if(key < 0)
  {
      printf("creat key failure\n");
      return -1;
  }
  msgid=msgget(key,IPC_CREAT | 0777);
  if(msgid < 0)
  {
      printf("creat message queue failure\n");
      return -2;
  }
  pid=fork();
  if(pid < 0)
        return -3;
  if(pid > 0)//write type=10
  {
    wrbuf.mytype=11;// voltage data
      while(1)
    {
     memset(wrbuf.sendbuf,0,128);
     printf("please input data:\n");
     fgets(wrbuf.sendbuf,128,stdin);
     msgsnd(msgid,(void *)&wrbuf,128,0);
      }
  }
 
  //read
  if(pid == 0)  //read type=11
  {
      while(1)
      {
      memset(rdbuf.sendbuf,0,128);
      msgrcv(msgid,(void *)&rdbuf,128,10,0);
      printf("%s",rdbuf.sendbuf);
      }
  }
  msgctl(msgid,IPC_RMID,NULL);
  return 0;
}
posted @ 2017-02-26 16:50  奔涌吧,后浪  阅读(19)  评论(0编辑  收藏  举报