XSI消息队列的使用上存在一个问题:不能将他们与poll或者select一起使用,这是因为他们不能关联到文件描述符。然而我们可以通过使用Unix域套接字客服这一特点,为每个消息队列建立一个线程,在线程中接收消息,一旦有消息到达就通过UNIX域套接字一端发送,在套接字的另一端可以使用poll或者select读取消息。这样可以达到同时监听多个消息队列的目的。具体看代码:
例如: ./send 0x123 "hello world" ;说明参数一为队列的键值,参数二为消息的内容
#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" ;说明参数一为队列的键值,参数二为消息的内容