消息队列返回值发送消息后怎么得返回值

自由、创新、研究、探索
Linux/Windows Mono/DotNet [ Open Source .NET Development/ 使用开源工具进行DotNet软件开发]锐意进取,志存高远.成就梦想,只争朝夕.从你开始,创新世界.【That I exist is a perpetual supprise which is life. Focus on eCommerce】
我会用几篇博客总结一下在Linux中进程之间通信的几种方法,我会把这个开头的摘要部分在这个系列的每篇博客中都打出来
进程之间通信的方式
共享存储区
套接字(socket)
进程间通信(一)&管道传送门:
这次主要写的是消息队列,之前讲过的管道和消息队列在本质上就有很大的区别,管道是一个文件,而消息队列是一个数据结构(类似于链表)。这说明了,管道文件是存放在磁盘上的,关机也会存在(尤其是命名管道更为显而易见,你不删除他他就搁那呆着),而消息队列是存在于内核中的内存,显而易见,关机就没了。
更关键的是,内存他快呀,比磁盘I/O快多了,为啥要用那么慢的管道。而且消息队列是可以直接完成没有亲缘关系的进程之间的通信的。但是结构比起管道要复杂,用到了很多结构体。内容有些多。先写一下和管道的主要区别,可以更直观的进行对比
匿名管道是跟随进程的,消息队列是跟随内核的,也就是说进程结束之后,匿名管道就死了,但是消息队列还会存在(除非显示调用函数销毁)
管道是文件,存放在磁盘上,访问速度慢,消息队列是数据结构,存放在内存,访问速度快
管道是数据流式存取,消息队列是数据块式存取
那么从头开始吧:
如何创建一个消息队列
在C库函数中有一个系统调用可以创建一个消息队列,那就是msgget,跟这个函数有关的其他函数也会一并给出来
函数原型: int msgget(key_t key, int msgflg)
头文件:#include &sys/types.h& #include &sys/ipc.h& &#include &sys/msg.h&
第一个参数是一个标识数据结构唯一的key键值,可以给IPC_PRIVATE让内核自动给,也可以自己调用ftok函数绑定一个
第二个参数是创建消息队列的参数,有IPC_CREAT 和 IPC_EXCL
单独使用IPC_CREAT,如果该消息队列已经存在(就是该key_t对象已经拿去被创建过一个队列了),打开该队列并返回,如果不存在,就创建一个返回
单独使用IPC_EXCL没有意义
两个参数一起使用(IPC_CREAT | IPC_EXCL),如果该队列存在,出错返回,如果不存在创建一个返回,也就是说这样使用一定会获得一个新队列
返回值,成功返回标志消息队列的唯一的一个int,失败返回-1
函数原型:key_t ftok(const char *pathname,int proj_id)
头文件:#include &sys/types.h& &#include &sys/ipc.h&
没啥好解析的,第一个参数就是给个路径(目录)就成了
第二个就是给个int值,没啥特殊要求,ftok本质就是把这个proj_id和pathname绑定在一起罢了
相关函数就这么多,到这里就可以开心的创建一个新的消息队列了,那么怎么看我们创建出来的消息队列呢?怎么销毁他呢?
先用命令看一下,使用ipcs -q就可查看消息队列的状态,这里我创建了一个消息队列,下面来销毁它
使用ipcrm -q msqid就可以销毁一个消息队列,我已经把刚才创建的消息队列销毁了
那么如何通过C函数销毁一个消息队列?使用msgctl函数
函数原型: int msgctl(int msgid ,int cmd ,struct msgid_ds *buf)
头文件:#include &sys/types.h& &#include &sys/ipc.h& &#include &sys/msg.h&
第一个参数就是创建好的标识msg的int变量
第二个参数有很多,这里介绍两个,先说主要的销毁,IPC_RMID,设置了这个之后第三个参数就没必要设置了给个0就成
第二个参数设置成IPC_SET的时候表示对消息队列进行初始化,这时第三个参数就有用了,但是我这里没用到就不话费篇幅详细解释了,贴出结构看看就成
这里提一下,消息队列的一个缺点,这里说到IPC_SET对消息队列的初始化,就是说消息队列的创建和初始化是分开的,这样设计不是很好,因为有线程安全的问题,当一个线程创建了消息队列还没初始化,另一个线程直接开始执行访问的操作就很尴尬了
1 struct msginfo {
/* Size in kibibytes of buffer pool
unused within kernel */
/* Maximum number of entries in message
unused within kernel */
/* Maximum number of bytes that can be
written in a single message */
/* Maximum number of bytes that can be
used to initialize
msg_qbytes during queue creation
(msgget(2)) */
/* Maximum number of message queues */
unused within kernel */
/* Maximum number of messages on all queues
unused within kernel */
unused within kernel */
使用消息队列
提到使用消息队列无非就是消息的写入和消息的读出,这涉及两个函数和一个结构体
先说发送函数
函数原型:int msgsnd(int msgid,const void *msgp,size_t msgsz,int msgflg)
头文件:#include &sys/types.h& &#include &sys/ipc.h& & #include &sys/msg.h&
第一个还是消息队列号
第二个是一个结构体的指针,这个结构体叫做msgbuf在内核中有(应该是有的。。。没有就自己写一个放程序里),必要的,这个就是传输数据的数据块,没了它就没得传了,可不能随便设置为0
第三个就是传输的消息长度(一般你的数据有多长就写多长,不是msgbuf对象的总大小)
第四个是传送方式(无阻塞啊什么的)的参数,我的程序没有使用所以我设置为0了
在列接受函数之前必须把结构体放出来,不然下面就懵逼了
1 struct msgbuf {
/* message type, must be & 0 */
char mtext[1];
/* message data */
从mtype讲起,因为队列是好多进程(或者说是线程)都拿来用的,比如4个进程共用一个消息队列,两两之间进行通信,就有必要标识哪两个进程是一组的,哪块数据是属于你们组的,不能乱拿是不是,这个mtype就是用来标识的,但是一定要大于0,我一开始设置为0一直报参数错误,查了文档才发现自己蠢了。。。
mtext存放的就是你要传输的数据了,怎么大小只有1?当然不能只有1,我自己写的msgbuf就有1024长度。。。所以还是自己写爽啊
&可以说接受函数了
函数原型:ssize_t msgrcv(int msgid,const void *msgp,size_t msgsz,long msgtyp,int msgflg)
头文件同msgsnd函数
只用看标红部分就成了,其他的和msgsnd一样
msgtyp就是用来表示我(当前进程)拿数据的时候,只拿(msgbuf对象中的mtype)和我传入的msgtyp一样的数据块(msgbuf对象)
&成功返回长度,失败返回-1
事已至此,基本操作就说完了,废话少说,show me the code
我的程序分为comm.h(公共头文件) &comm.c(封装基本函数) server.c(建议服务器端) client.c(简易客户端)一共4个文件
完成了服务器端和客户端的简单通信(回合制聊天(误))
1 #include &stdio.h&
2 #include &unistd.h&
3 #include &sys/msg.h&
4 #include &sys/types.h&
5 #include &sys/ipc.h&
6 #include &string.h&
7 #include &stdlib.h&
8 #include &errno.h&
9 #include &memory.h&
12 #define _PATH_NAME_ "/tmp"
13 #define _PROJ_ID_ 0x666
14 #define _SIZE_ 1024
16 static int comm_create_msg_set(int flags);
17 int create_msg_set();
18 int get_msg_set();
19 void destory_msg_set(int msg_id);
20 void send_msg(int msg_id,long msgtype,char * buf);
21 void receive_msg(int msg_id,long msgtype,char *buf);
25 struct msgbuf
char mtext[_SIZE_];
1 #include "comm.h"
2 static int comm_create_msg_set(int flags)
key_t _key=ftok(_PATH_NAME_,_PROJ_ID_);
if(_key&0)
printf("%d:%s",errno,strerror(errno));
int msg_id=msgget(_key,flags);
if(msg_id&0)
printf("%d:%s",errno,strerror(errno));
return msg_
18 int get_msg_set()
key_t _key=ftok(_PATH_NAME_,_PROJ_ID_);
int flags=IPC_CREAT;
return comm_create_msg_set(flags);
26 int create_msg_set()
key_t _key=ftok(_PATH_NAME_,_PROJ_ID_);
int flags=IPC_CREAT | IPC_EXCL;
return comm_create_msg_set(flags);
34 void send_msg(int msg_id,long msgtype,char *buf)
memset(buf,'\0',strlen(buf)+1);
ssize_t _size=read(0,buf,_SIZE_);
if(_size&0)
buf[_size-1]='\0';
struct msgbuf _
memset(&_mbuf,'\0',sizeof(struct msgbuf));
_mbuf.mtype=
strcpy(_mbuf.mtext,buf);
if(msgsnd(msg_id,&_mbuf,_size,0)&0)
printf("send error,%d:%s",errno,strerror(errno));
53 void receive_msg(int msg_id , long msgtype ,char *buf)
struct msgbuf _
memset(&_mbuf,'\0',sizeof(struct msgbuf));
_mbuf.mtype=0;
if(msgrcv(msg_id,&_mbuf,_SIZE_,msgtype,0)&0)
printf("recv error %d:%s",errno,strerror(errno));
strcpy(buf,_mbuf.mtext);
65 void destory_msg_set(int msg_id)
if(msgctl(msg_id,IPC_RMID,0)&0)
printf("%d:%s",errno,strerror(errno));
1 #include "comm.h"
2 long c_type=1;
3 long s_type=22;
4 int main()
int msg_id=create_msg_set();
char buf[_SIZE_];
memset(buf,'\0',sizeof(buf));
receive_msg(msg_id,c_type,buf);
if(strcasecmp(buf,"quit")==0)
printf("client # %s\n",buf);
printf("clent say done ! Please Input:");
fflush(stdout);
memset(buf,'\0',sizeof(buf));
send_msg(msg_id,c_type,buf);
destory_msg_set(msg_id);
1 #include "comm.h"
4 long c_type=1;
5 long s_type=2;
7 int main()
int msg_id = get_msg_set();
char buf[_SIZE_];
memset(buf,'\0',sizeof(buf));
send_msg(msg_id,c_type,buf);
if(strcasecmp(buf,"quit")==0)
memset(buf,'\0',sizeof(buf));
receive_msg(msg_id,c_type,buf);
printf("server # %s\n",buf);
printf("server say done ! Please Input:");
fflush(stdout);
阅读(...) 评论()
随笔 - 16391
评论 - 1491博客分类:
openstack中的消息队列
1openstack中消息队列的使用
nova中的每个组件都会连接消息服务器,一个组件可能是一个消息发送者(如API、Scheduler),也可能是一个消息接收者(如compute、volume、network)。发送消息有两种方式:同步调用rpc.call和异步调用rpc.cast
openstack内部一些对象:
lTopic Publisher:该对象在进行rpc.call或rpc.cast时创建,每个对象都会连接同一个topic类型的交换器,消息发送完毕后对象被回收。
lDirect Publisher:该对象在进行rpc.call调用时创建,用于向消息发送者返回响应。该对象会根据接收到的消息属性连接一个direct类型的交换器。
lDirect Consumer:该对象在进行rpc.call调用时创建,用于接收响应消息。每一个对象都会通过一个的队列连接一个direct类型的交换器(队列和交换器以UUID命名)。
lTopic Consumer:该对象在内部服务初始化时创建,在服务过程中一直存在。用于从队列中接收消息,调用消息属性中指定的函数。该对象通过一个共享队列或一个私有队列连接一个topic类型的交换器。每一个内部服务都有两个topic consumer,一个用于rpc.cast调用(此时连接的是binding-key为“topic”的共享队列);另一个用于rpc.call调用(此时连接的是binding-key为“topic.host”的私有队列)
lTopic Exchange:topic类型交换器,每一个消息代理节点只有一个topic类型的交换器。
lDirect Exchange:direct类型的交换器,存在于rpc.call调用过程中,对于每一个rpc.call的调用,都会产生该对象的一个实例。
lQueue Element:消息队列。可以共享也可以私有。routing-key为“topic”的队列会在相同类型的服务中共享(如多个compute节点共享一个routing-key为“topic”的队列)。
各个对象的工作模型:
openstack中默认使用kombu(实现AMQP协议的Python函数库)连接RabbitMQ服务器。消息的收/发者都需要一个Connetion对象连接RabbitMQ服务器。
2消息队列性能影响因素
消息队列在openstack整个架构中扮演着至关重要(交通枢纽)的作用,正是因为openstack部署的灵活性、模块的松耦合、架构的扁平化,反而使openstack更加依赖于消息队列(不一定使用RabbitMQ,可以是其他的消息队列产品),所以消息队列收发消息的性能和消息队列的HA能力直接影响openstack的性能。
在openstack中的任意时间点,影响消息服务器性能的的因素如下:
l在rpc.call调用过程中:rpc.call的调用数决定了direct类型的交换器个数,相关的私有队列个数以及监听私有队列的direct consumer的个数。
l工作者线程(内部服务)个数:相同属性的工作者线程(如compute节点)会共享一个队列,但每一个工作者线程都有一个私有队列。相同属性的工作者线程个数也决定了在topic类型交换器上的routing key的个数。
在实验环境下,主机名为kong,openstack各个组件启动后,会创建:
?Exchanges
1.nova (topic exchange)
1.compute.kong
3.network.kong
5.volume.kong
7.scheduler.kong
8.scheduler
使用消息队列时有如下几个(Consumer类)属性:
?Durable:该属性决定了交换器和队列是否持久化,如持久化,则交换器和队列在RabbitMQ服务重启后仍然继续工作,否则交换器和队列的信息被清空。AMQP协议规定,持久化的队列只能绑定到持久化的交换器。
?Auto_delete:如果设置,则当所有队列结束后,交换器自动删除。默认为False。
?Exclusive:队列是否私有,如果该属性设置,则Auto_delete属性会自动生效。默认为False。
?Auto_ack:收到消息时是否自动发送回执。默认是False,要求消息接收者手动处理回执。
?No_ack:如果设置会提高性能,但会降低可靠性。
?Delivery_mode:消息的传输类型。目前RabbitMQ支持两种类型:
n1或者“transient”:消息存储在内存,当服务器宕机或重启时消息丢失
n2或者“persistent”:消息会同时在内存和硬盘保存,服务器宕机或重启时消息不丢失
在大规模部署的情况下,势必会对单节点的RabbitMQ server造成较大的负载,一旦发生单节点故障,整个openstack服务都会瘫痪。所以,部署时可以考虑使用RabbitMQ的HA等高级部署特性,具体参见RabbitMQ相关文档,在此不再赘述。
3.1服务的启动
根据以上分析可知,nova组件服务启动时会创建TopicConsumer,以“nova-compute”服务启动为例,在服务的启动过程中,会调用service::start()方法,在该方法中:
3.1.1conn是什么?
是nova.openstack.common.amqp.ConnectionContext对象,这个对象是由RPC实现类调用create_connection()方法创建。RPC在openstack中有四种实现:
具体使用哪一种根据配置文件确定,默认的配置项是:
rpc_backend=nova.rpc.impl_kombu
ConnectionContext对象包含两个字段:
üconnection_pool:一个Connection对象池(继承自eventlet.pools.Pool),用于生成Connection对象。
üconnection:由connection_pool 生成。nova.openstack.common.rpc.impl_komku.Connection对象。该对象在初始化时,会根据配置的参数和策略连接RabbitMQ服务器。
3.1.2rpc_dispatcher是什么?
RpcDispatcher对象。该对象中有属性callbacks,是一个包含ComputeManager对象的列表。用于接收到消息之后的处理。
3.1.3三个create_consumer方法干了什么?
以第一个为例,在该函数中,创建了TopicConsumer对象。
3.1.4consume_in_thread方法
在方法的实现里,又借助了evlentlet库创建超线程。在超线程主函数中调用了TopicConsumer对象的consume()方法(该类没有实现该方法,直接调用父类)。
对消息的处理包括:从消息中获取接口名称、获取接口参数、调用ComputeManager对象相应方法。
至此,“nova-compute”服务启动完成。
3.2消息的发送
以创建虚拟机为例,由前几篇文章可知,经过Scheduler模块的过滤后,将创建虚拟机消息发送到对应的compute节点。
cast_to_compute_host方法的实现:
rpc.cast最终会创建一个TopicPublisher对象,并调用该对象的send方法。
由上可知,TopicConsumer对象会向名为“nova”的exchange上, 以 “compute.host”为routing-key发送消息。此时消息会发送到在名为“compute.host”队列上监听的TopicConsumer对象。
浏览 10018
浏览: 247548 次
来自: 西安
请问,OpenStack在关心消息返回值的情况下,两个队列一发 ...
zfj_0928 写道引用1. 消息ACK,通知RabbitM ...
引用1. 消息ACK,通知RabbitMQ消息已被处理,可以从 ...
写的好,很感谢!
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
spring rabbitmq 怎样确认消息成功发送到了队列中
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。什么是消息队列?消息队列使用场景是怎样的?阿里用的消息队列是?什么是消息队列?消息队列使用场景是怎样的?阿里用的消息队列是?超牛财经百家号j简单粗暴一个例子搞定:什么是消息队列?小红是小明的姐姐。小红希望小明多读书,常寻找好书给小明看,之前的方式是这样:小红问小明什么时候有空,把书给小明送去,并亲眼监督小明读完书才走。久而久之,两人都觉得麻烦。后来的方式改成了:小红对小明说「我放到书架上的书你都要看」,然后小红每次发现不错的书都放到书架上,小明则看到书架上有书就拿下来看。书架就是一个消息队列,小红是生产者,小明是消费者。这就是消息队列。当然,也有侧重点,个人认为消息队列的主要特点是异步处理,主要目的是减少请求响应时间和解耦。所以主要的使用场景就是将比较耗时而且不需要即时(同步)返回结果的操作作为消息放入消息队列。同时由于使用了消息队列,只要保证消息格式不变,消息的发送方和接收方并不需要彼此联系,也不需要受对方的影响,即解耦和。这带来的好处有:1.小红想给小明书的时候,不必问小明什么时候有空,亲手把书交给他了,小红只把书放到书架上就行了。这样小红小明的时间都更自由。2.小红相信小明的读书自觉和读书能力,不必亲眼观察小明的读书过程,小红只要做一个放书的动作,很节省时间。3.当明天有另一个爱读书的小伙伴小强加入,小红仍旧只需要把书放到书架上,小明和小强从书架上取书即可(唔,姑且设定成多个人取一本书可以每人取走一本吧,可能是拷贝电子书或复印,暂不考虑版权问题)。4.书架上的书放在那里,小明阅读速度快就早点看完,阅读速度慢就晚点看完,没关系,比起小红把书递给小明并监督小明读完的方式,小明的压力会小一些。官方点说,这就是消息队列的四大好处:1.解耦每个成员不必受其他成员影响,可以更独立自主,只通过一个简单的容器来联系。小红甚至可以不知道从书架上取书的是谁,小明也可以不知道往书架上放书的人是谁,在他们眼里,都只有书架,没有对方。毫无疑问,与一个简单的容器打交道,比与复杂的人打交道容易一万倍,小红小明可以自由自在地追求各自的人生。2.提速小红选择相信「把书放到书架上,别的我不问」,为自己节省了大量时间。小红很忙,只能抽出五分钟时间,但这时间足够把书放到书架上了。3.广播小红只需要劳动一次,就可以让多个小伙伴有书可读,这大大地节省了她的时间,也让新的小伙伴的加入成本很低。4.削峰假设小明读书很慢,如果采用小红每给一本书都监督小明读完的方式,小明有压力,小红也不耐烦。反正小红给书的频率也不稳定,如果今明两天连给了五本,之后隔三个月才又给一本,那小明只要在三个月内从书架上陆续取走五本书读完就行了,压力就不那么大了。当然,使用消息队列也有其成本:1.引入复杂度毫无疑问,「书架」这东西是多出来的,需要地方放它,还需要防盗。2.暂时的不一致性假如妈妈问小红「小明最近读了什么书」,在以前的方式里,小红因为亲眼监督小明读完书了,可以底气十足地告诉妈妈,但新的方式里,小红回答妈妈之后会心想「小明应该会很快看完吧……」这中间存在着一段「妈妈认为小明看了某书,而小明其实还没看」的时期,当然,小明最终的阅读状态与妈妈的认知会是一致的,这就是所谓的「最终一致性」。消息队列其中一种模式那么,该使用消息队列的情况需要满足什么条件呢?1.生产者不需要从消费者处获得反馈引入消息队列之前的直接调用,其接口的返回值应该为空,这才让明明下层的动作还没做,上层却当成动作做完了继续往后走——即所谓异步——成为了可能。小红放完书之后小明到底看了没有,小红根本不问,她默认他是看了,否则就只能用原来的方法监督到看完了。2.容许短暂的不一致性妈妈可能会发现「有时候据说小明看了某书,但事实上他还没看」,只要妈妈满意于「反正他最后看了就行」,异步处理就没问题。如果妈妈对这情况不能容忍,对小红大发雷霆,小红也就不敢用书架方式了。3.确实是用了有效果即解耦、提速、广播、削峰这些方面的收益,超过放置书架、监控书架这些成本。否则如果是盲目照搬,「听说老赵家买了书架,咱们家也买一个」,买回来却没什么用,只是让步骤变多了,还不如直接把书递给对方呢,那就不对了。所以在软件的正常功能开发中,并不需要去刻意的寻找消息队列的使用场景,而是当出现性能瓶颈时,去查看业务逻辑是否存在可以异步处理的耗时操作,如果存在的话便可以引入消息队列来解决。否则盲目的使用消息队列可能会增加维护和开发的成本却无法得到可观的性能提升,那就得不偿失了。阿里的消息队列:就隐藏在下面的阿里最全技术架构体系图中,可自己慢慢查看。因为上传后头条压缩问题,可能图片不够清晰。有需要高清完整大图的可关注后私信“阿里”二字领取。本头条号内有多个专题,如【数据结构】、【netty专题】、【dubbo专题】、【mysql优化专题】、【redis专题】、【高并发专题】等优质好文。觉得有收获的可以收藏关注,欢迎骚扰,一起学习,共同进步。本文仅代表作者观点,不代表百度立场。系作者授权百家号发表,未经许可不得转载。超牛财经百家号最近更新:简介:超牛财经有多牛,等你来验证作者最新文章相关文章博客分类:
就时你指定的文件名该文件必须是存在而且可以访问的,是子序号,虽
然为,但是只有个比特被使用。
类型的值,失败返回
msgget()函数的第一个参数是消息队列对象的关键字,函数将它与已有的消息队列对象的关键字进行比较来判断消息队列对象是否已经创建。而函数进行的具体操作是 由控制的。它可以取下面的几个值:IPC_CREAT :IPC_EXCL:一起使用(用连接),如果消息对象不存在则创建之,否
则产生一个
成功时返回队列失败返回,错误原因存于中
EEXIST (Queue exists, cannot create)EIDRM (Queue is marked for deletion)ENOENT (Queue does not exist)ENOMEM (Not enough memory to create queue)ENOSPC (Maximum queue limit exceeded)
传给函数的第一个参数是消息队列对象的标识符(由函数得
到),第二个参数指向要发送的消息所在的内存,第三个参数是要发送信息
的msgsz = sizeof(struct mymsgbuf) - sizeof(long);第四个参数是控制函数行为的标志,可以取以下的值:0,忽略标志位;IPC_NOWAIT,如果消息队列已满,消息将不被写入队列,控制权返回调用函数的线程。如果不指定这个参数,线程将被阻塞直到消息被可以被写入。
smgbuf结构体定义如下:
struct smgbuf
msgflg 可设置为 。如果消息队列已满或其他情况无法送入消息,则立即
-1 on error: errno = EAGAIN (queue is full, and IPC_NOWAIT was asserted)EACCES (permission denied, no write permission)EFAULT (msgp address isn't accessable – invalid)EIDRM (The message queue has been removed)EINTR (Received a signal while waiting to write)EINVAL (Invalid message queue identifier, nonpositivemessage type, or invalid message size)ENOMEM (Not enough memory to copy message buffer)
函数的前三个参数和函数中对应的参数的含义是相同的。第四个参数
指定了函数从队列中所取的消息的类型。函数将从队列中搜索类型与之匹配的消息并将 之的值是零的话,函数将不做类型检查而自动返
回0,表示忽略;IPC_NOWAIT,如果消息队列为空,则返回一个,并将控制权交回调用函数的进程。如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件 的正在等待消息的时候队列被删除,就会被返回。如果
进就会被返回。MSG_NOERROR,如果函数取得的消息长度大于,将只返回长度的信息,剩下的部分被丢弃了。如果不指定这个参数,将被返回,而消息则留在队列中不
被当消息从队列内取出后,相应的消息就从队列中删除了。
与 结构体中的相同的信息
小于等于绝对值的信息
,则截断信息而不报错。
成功时返回所获取信息的长度,失败返回,错误信息存于
Number of bytes copied into message buffer-1 on error: errno = E2BIG (Message length is greater thanmsgsz,EACCES (No read permission)EFAULT (Address pointed to by msgp is EIDRM (Queue was removed during EINTR (Interrupted by arriving signal)EINVAL (msgqid invalid, or msgsz less than 0)ENOMSG (IPC_NOWAIT asserted, and no
#include &stdio.h&
#include &string.h&
#include &stdlib.h&
#include &errno.h&
#include &unistd.h&
#include &sys/types.h&
#include &sys/ipc.h&
#include &sys/stat.h&
#include &sys/msg.h&
#define MSG_FILE "server.c"
#define BUFFER 255
#define PERM S_IRUSR|S_IWUSR
struct msgtype {
char buffer[BUFFER+1];
int main()
if((key=ftok(MSG_FILE,'a'))==-1)
fprintf(stderr,"Creat Key Error:%s\a\n",strerror(errno));
if((msgid=msgget(key,PERM|IPC_CREAT|IPC_EXCL))==-1)
fprintf(stderr,"Creat Message Error:%s\a\n",strerror(errno));
msgrcv(msgid,&msg,sizeof(struct msgtype),1,0);
fprintf(stderr,"Server Receive:%s\n",msg.buffer);
msg.mtype=2;
msgsnd(msgid,&msg,sizeof(struct msgtype),0);
#include &stdio.h&
#include &string.h&
#include &stdlib.h&
#include &errno.h&
#include &sys/types.h&
#include &sys/ipc.h&
#include &sys/msg.h&
#include &sys/stat.h&
#define MSG_FILE "server.c"
#define BUFFER 255
#define PERM S_IRUSR|S_IWUSR
struct msgtype {
char buffer[BUFFER+1];
int main(int argc,char **argv)
if(argc!=2)
fprintf(stderr,"Usage:%s string\n\a",argv[0]);
if((key=ftok(MSG_FILE,'a'))==-1)
fprintf(stderr,"Creat Key Error:%s\a\n",strerror(errno));
if((msgid=msgget(key,PERM))==-1)
fprintf(stderr,"Creat Message Error:%s\a\n",strerror(errno));
msg.mtype=1;
strncpy(msg.buffer,argv[1],BUFFER);
msgsnd(msgid,&msg,sizeof(struct msgtype),0);
memset(&msg,'\0',sizeof(struct msgtype));
msgrcv(msgid,&msg,sizeof(struct msgtype),2,0);
fprintf(stderr,"Client receive:%s\n",msg.buffer);
浏览 25444
home198979
浏览: 976327 次
来自: 深圳
浏览量:58039
浏览量:32216
浏览量:49878
不一定哦,就算大小相当,in 和 exists的性能也会很大差 ...
[size=x-small][/size]
q 写道还是佩服写c的用其它语言一样可以实现 ...
还是佩服写c的
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'}

我要回帖

更多关于 mq 消息队列 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信