XSI消息队列与复用IO的结合实例

本文介绍了一种利用XSI消息队列与Unix域套接字结合的技术方案,通过为每个消息队列创建一个专门的线程来接收消息,并通过Unix域套接字转发消息,从而实现利用poll或select同时监听多个消息队列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

XSI消息队列的使用上存在一个问题:不能将他们与poll或者select一起使用,这是因为他们不能关联到文件描述符。然而我们可以通过使用Unix域套接字客服这一特点,为每个消息队列建立一个线程,在线程中接收消息,一旦有消息到达就通过UNIX域套接字一端发送,在套接字的另一端可以使用poll或者select读取消息。这样可以达到同时监听多个消息队列的目的。具体看代码:
#include"apue.h"
#include<poll.h>
#include<pthread.h>
#include<sys/msg.h>
#include<sys/socket.h>

#define NQ 3
#define MAXMSZ  512
#define KEY 0x123

struct threadinfo{  //传递给线程的数据类型
	int qid;
	int fd;
};

struct mymesg{    //消息类型
	long mtype;
	char mtext[MAXMSZ];
};

void* helper(void* arg)
{
	int n;
	struct mymesg m;
	struct threadinfo *tip=arg;
	
	for(;;){
		memset(&m,0,sizeof(m));
		if((n=msgrcv(tip->qid,&m,MAXMSZ,0,MSG_NOERROR))<0) //接收消息(没有消息时阻塞)
			err_sys("msgrcv error");
		if(write(tip->fd,m.mtext,n)<0)   //将消息发送到Unix域套接字
			err_sys("wirte error");
		}
}

int main()
{
	int i,n,err;
	int fd[2];
	int qid[NQ];
	struct pollfd pfd[NQ];
	struct threadinfo ti[NQ];
	pthread_t tid[NQ];
	char buf[MAXMSZ];
	
	for(i=0;i<NQ;i++){
		if((qid[i]=msgget((KEY+i),IPC_CREAT | 0666))<0)
			err_sys("msgget error");
		printf("queue ID %d is %d\n",i,qid[i]);
		
		if(socketpair(AF_UNIX,SOCK_DGRAM,0,fd)<0)
			err_sys("socketpair error");
		pfd[i].fd=fd[0];   //监听Unix域套接字
		pfd[i].events=POLLIN;
		ti[i].qid=qid[i];
		ti[i].fd=fd[1];
		if((err=pthread_create(&tid[i],NULL,helper,&ti[i]))!=0) //为每个消息队列建立线程
			err_exit(err,"pthread_create error");
		}
	
	for(;;){
		if(poll(pfd,NQ,-1)<0)
			err_sys("poll error");
		for(i=0;i<NQ;i++){
			if(pfd[i].revents & POLLIN){
				if((n=read(pfd[i].fd,buf,sizeof(buf)))<0)  //接受消息
					err_sys("read error");
				buf[n]=0;
				printf("queue id %d,message %s\n",qid[i],buf);
				}
			}
		}
	
	exit(0);
}
#include"apue.h"   //发送消息的代码
#include<sys/msg.h>
#define MAXMSZ 512
struct mymesg{
	long mtype;
	char mtext[MAXMSZ];
};

int main(int argc,char**argv)
{
	key_t key;
	long qid;
	size_t nbytes;
	struct mymesg m;
	
	if(argc!=3){
		fprintf(stderr,"usage:sendmsg KEY message\n");
		exit(1);
	}
	key=strtol(argv[1],NULL,0);
	if((qid=msgget(key,0))<0)
		err_sys("can't open queue key %s",argv[1]);
	memset(&m,0,sizeof(m));
	strncpy(m.mtext,argv[2],MAXMSZ-1);
	nbytes=strlen(m.mtext);
	m.mtype=1;
	if(msgsnd(qid,&m,nbytes,0)<0)
		err_sys("can't send message");
	exit(0);
}

例如: ./send 0x123 "hello world" ;说明参数一为队列的键值,参数二为消息的内容


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值