消息队列

  消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。可以通过发送消息来避免命名管道的同步和阻塞问题。但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制。
  Linux用宏MSGMAX和MSGMNB来限制一条消息的最大长度和一个队列的最大长度。
 
msgget函数
  创建和访问一个消息队列。
int msgget(key_t, key, int msgflg); 
  key:  与其他的IPC机制一样,程序必须提供一个键来命名某个特定的消息队列。
  msgflg:  表示消息队列的访问权限。可以与IPC_CREAT做或操作,表示当key所命名的消息队列不存在时创建一个消息队列。
  返回值:返回一个以key命名的消息队列的标识符,非零整数,-1表示失败。
 
msgsnd函数
  把消息添加到消息队列中。
int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);
  msgid:是由msgget函数返回的消息队列标识符。
  msg_ptr:是一个指向准备发送消息的指针,所指向的消息结构一定是以一个长整型成员变量开始的结构体,接收函数将用这个成员来确定消息的类型。
  msg_sz:是msg_ptr指向的消息的长度,而不是整个结构体的长度,也就是说msg_sz是不包括长整型消息类型成员变量的长度。

  msgflg:用于控制当前消息队列满或队列消息到达系统范围的限制时将要发生的事情。
  消息结构如下:
    struct my_message{
long int message_type;
/* The data you wish to transfer*/
};

  如果调用成功,消息数据的一份副本将被放到消息队列中,并返回0,失败时返回-1.

 
msgrcv函数
  该函数用来从一个消息队列获取消息。
int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg); 
  msgid, msg_ptr, msg_st:作用跟msgsnd函数一样。
  msgtype:接收优先级。0:获取队列中的第一个消息。大于0:获取具有相同消息类型的第一个信息。小于0:获取类型等于或小于msgtype的绝对值的第一个消息。
  msgflg:用于控制当队列中没有相应类型的消息可以接收时将发生的事情。
  调用成功时,该函数返回放到接收缓存区中的字节数,消息被复制到由msg_ptr指向的用户分配的缓存区中,然后删除消息队列中的对应消息。失败时返回-1.
 
msgctl函数
  该函数用来控制消息队列,它与共享内存的shmctl函数相似
int msgctl(int msgid, int command, struct msgid_ds *buf); 
  command:是将要采取的动作,它可以取3个值,
          IPC_STAT:把msgid_ds结构中的数据设置为消息队列的当前关联值,即用消息队列的当前关联值覆盖msgid_ds的值。
          IPC_SET:如果进程有足够的权限,就把消息列队的当前关联值设置为msgid_ds结构中给出的值
          IPC_RMID:删除消息队列
  buf:是指向msgid_ds结构的指针,它指向消息队列模式和访问权限的结构。
msgid_ds结构至少包括以下成员:
struct msgid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};
  返回值:0表示成功,-1表示失败。
 

使用

接收信息:
    #include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/msg.h> struct msg_st
{
long int msg_type;
char text[BUFSIZ];
}; int main()
{
int running = ;
int msgid = -;
struct msg_st data;
long int msgtype = ; //注意1 //建立消息队列
msgid = msgget((key_t), | IPC_CREAT);
if(msgid == -)
{
fprintf(stderr, "msgget failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}
//从队列中获取消息,直到遇到end消息为止
while(running)
{
if(msgrcv(msgid, (void*)&data, BUFSIZ, msgtype, ) == -)
{
fprintf(stderr, "msgrcv failed with errno: %d\n", errno);
exit(EXIT_FAILURE);
}
printf("You wrote: %s\n",data.text);
//遇到end结束
if(strncmp(data.text, "end", ) == )
running = ;
}
//删除消息队列
if(msgctl(msgid, IPC_RMID, ) == -)
{
fprintf(stderr, "msgctl(IPC_RMID) failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}

发送信息:

    #include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>
#include <errno.h> #define MAX_TEXT 512
struct msg_st
{
long int msg_type;
char text[MAX_TEXT];
}; int main()
{
int running = ;
struct msg_st data;
char buffer[BUFSIZ];
int msgid = -; //建立消息队列
msgid = msgget((key_t), | IPC_CREAT);
if(msgid == -)
{
fprintf(stderr, "msgget failed with error: %d\n", errno);
exit(EXIT_FAILURE);
} //向消息队列中写消息,直到写入end
while(running)
{
//输入数据
printf("Enter some text: ");
fgets(buffer, BUFSIZ, stdin);
data.msg_type = ; //注意2
strcpy(data.text, buffer);
//向队列发送数据
if(msgsnd(msgid, (void*)&data, MAX_TEXT, ) == -)
{
fprintf(stderr, "msgsnd failed\n");
exit(EXIT_FAILURE);
}
//输入end结束输入
if(strncmp(buffer, "end", ) == )
running = ;
sleep();
}
exit(EXIT_SUCCESS);
}
结果:
➜  jiangtf  ./send
Enter some text: abs
You wrote: abs Enter some text: tjdf
You wrote: tjdf Enter some text: end
You wrote: end [] + done ./a.out
 
 
消息类型详解
  注意接收文件中的变量msgtype其值为0,表示获取队列中第一个可用的消息。再来看看发送文件中while循环中的语句 data.msg_type = 1,它用来设置发送的信息的信息类型,即其发送的信息的类型为1。所以程序msgreceive能够接收到程序msgsend发送的信息。
  如果把注意1中 long int msgtype = 0 改变为 long int msgtype = 2 ,msgreceive将不能接收到程序msgsend发送的信息。因为在调用msgrcv函数时,如果msgtype(第四个参数)大于零,则将只获取具有相同消息类型的第一个消息,修改后获取的消息类型为2,而msgsend发送的消息类型为1,所以不能被msgreceive程序接收。重新编译msgreceive.c文件并再次执行,其结果如下:
➜  jiangtf  ./send
Enter some text: asd
Enter some text: intad
Enter some text: end

消息队列与命名管道的区别

  在命名管道中,发送数据用write,接收数据用read,则在消息队列中,发送数据用msgsnd,接收数据用msgrcv。而且它们对每个数据都有一个最大长度的限制。与命名管道相比,消息队列的优势在于:

  1、消息队列也可以独立于发送和接收进程而存在,从而消除了在同步命名管道的打开和关闭时可能产生的困难。

  2、同时通过发送消息还可以避免命名管道的同步和阻塞问题,不需要由进程自己来提供同步方法。

  3、接收程序可以通过消息类型有选择地接收数据,而不是 像命名管道中那样,只能默认地接收。

 
参考:http://www.cnblogs.com/lidabo/p/4323807.html

网络通信 --> 消息队列的更多相关文章

  1. Netty构建分布式消息队列(AvatarMQ)设计指南之架构篇

    目前业界流行的分布式消息队列系统(或者可以叫做消息中间件)种类繁多,比如,基于Erlang的RabbitMQ.基于Java的ActiveMQ/Apache Kafka.基于C/C++的ZeroMQ等等 ...

  2. Netty构建分布式消息队列实现原理浅析

    在本人的上一篇博客文章:Netty构建分布式消息队列(AvatarMQ)设计指南之架构篇 中,重点向大家介绍了AvatarMQ主要构成模块以及目前存在的优缺点.最后以一个生产者.消费者传递消息的例子, ...

  3. 消息队列NetMQ 原理分析2-IO线程和完成端口

    消息队列NetMQ 原理分析2-IO线程和完成端口 前言 介绍 目的 IO线程 初始化IO线程 Proactor 启动Procator线程轮询 处理socket 获取超时时间 从完成端口获取处理完的状 ...

  4. 流处理与消息队列------《Designing Data-Intensive Applications》读书笔记16

    上一篇聊了聊批处理的缺点,对于无界数据来说,流处理会是更好的选择,"流"指的是随着时间的推移逐步增加的数据.消息队列可以将这些流组织起来,快速的在应用程序中给予反馈.但是消息队列与 ...

  5. Python RabbitMQ消息队列

    python内的队列queue 线程 queue:不同线程交互,不能夸进程 进程 queue:只能用于父进程与子进程,或者同一父进程下的多个子进程,进行交互 注:不同的两个独立进程是不能交互的.   ...

  6. 消息队列库——ZeroMQ

    消息队列库——ZeroMQ ZeroMQ(简称ZMQ)是一个基于消息队列的多线程网络库,其对套接字类型.连接处理.帧.甚至路由的底层细节进行抽象,提供跨越多种传输协议的套接字. ZMQ是网络通信中新的 ...

  7. 消息队列ZeroMQ

    消息队列概念 消息队列技术是分布式应用间交换信息的一种技术.消息队列可以驻留在内存或者磁盘上,队列存储消息直到它们被应用程序读走.通过消息队列,应用程序可以独立的执行,它们不需要知道彼此的位置,或者在 ...

  8. 通信与实际用例应用(消息队列和进程撰写的ATM机与消息队列的五子棋对站)

    int semget(key_t key, int nsems, int semflg); 功能:创建信号量或获取信号量 nsems:信号量的数量 semflg: IPC_CREAT|IPC_EXEC ...

  9. 消息队列rabbitmq/kafka

    12.1 rabbitMQ 1. 你了解的消息队列 rabbitmq是一个消息代理,它接收和转发消息,可以理解为是生活的邮局.你可以将邮件放在邮箱里,你可以确定有邮递员会发送邮件给收件人.概括:rab ...

随机推荐

  1. 获取NVIDIA显卡的温度

    NVIDIA显卡在硬件上有温度传感器,可以感知显卡的运行环境.温度数据的获取,一般是通过调用NVIDIA的SDK的相关函数即可.SDK的下载的网址(https://developer.nvidia.c ...

  2. MFC 多线程及线程同步

    一.MFC对多线程编程的支持 MFC中有两类线程,分别称之为工作者线程和用户界面线程.二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环. 工作者线程没有消息机制,通常 ...

  3. AM3358--Uboot支持LCD输出1024*768

    1. uboot/include/lcd/tq3358_fb.h #define TFT240320 1 #define TFT320240 2 #define TFT480272 3//T43(天嵌 ...

  4. Error Code: 1630. FUNCTION rand.string does not exist

    1.错误描述 13:50:13 call new_procedure Error Code: 1630. FUNCTION rand.string does not exist. Check the ...

  5. DirectShow学习笔记总结

    DirectShow是微软公司在ActiveMovie和Video for Windows的基础上推出的新一代基于COM(Component Object Model)的流媒体处理的开发包,9.0之前 ...

  6. CentOS配置日志集中管理

    ①首先有产生日志的服务器和储存日志的服务器 ②产生.接收日志的服务器都必须安装rsyslog服务(可以通过yum.rpm.源码包安装),rsyslog支持C/S模式 ③日志存储服务器需要编辑rsysl ...

  7. HashMap,LinkedHashMap,TreeMap对比

    共同点: HashMap,LinkedHashMap,TreeMap都属于Map:Map 主要用于存储键(key)值(value)对,根据键得到值,因此键不允许键重复,但允许值重复. 不同点: 1.H ...

  8. Struts2(七) Struts2访问Servlet的API

    当接受表单参数,向页面保持数据时.要用到Struts访问Servlet 的API .下面只做参考,有错误或不同意见可以发送邮箱2440867831@qq.com  .建议大家看struts文档,源代码 ...

  9. Java并发编程笔记4-线程池

    我们使用线程的时候就去创建一个线程,但是就会有一个问题: 如果并发的线程数量非常多,而且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会导致大大降低系统的效率,因为频繁创建线程和销毁线 ...

  10. 【视频编解码·学习笔记】11. 提取SPS信息程序

    一.准备工作: 回到之前SimpleH264Analyzer程序,找到SPS信息,并对其做解析 调整项目目录结构: 修改Global.h文件中代码,添加新数据类型UINT16,之前编写的工程中,UIN ...