消息队列是进程间通信之一,当然还有其他通信方式:管道,有名管道,内存共享,套接字等,下面详细介绍消息队列的用法。
首先介绍几个函数
int msgctl(int msgid , ing cmd , struct msgid_ds *buf);
int msgget(key_t key , ingt msgflg);
int msgrcv(ing msgid , void* msg_ptr , size_t msg_sz , long int msgtype , int msgflg);
int msgsnd(int msgid , const void* msg_ptr , size_t msg_sz , int msgflg);
这些函数的作用跟共享内存和信号量的作用是相同的。
int msgctl(int msgid , ing cmd , struct msgid_ds *buf);: 控制函数,用来控制消息列队的关闭等。
int msgget(key_t key , ingt msgflg);用来创建一个消息列队
int msgrcv(ing msgid , void* msg_ptr , size_t msg_sz , long int msgtype , int msgflg);用来接收一个消息
int msgsnd(int msgid , const void* msg_ptr , size_t msg_sz , int msgflg);用来发送一个消息
下面来看一个具体的例子。在这个例子中,我们将在客户端中对消息进行接收,在接收完所有的消息后,删除消息列队。
在服务器中,我们将发送消息到消息列队中,直到遇到end结束符为止。
发送消息源程序,命名为msgsend.c
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<unistd.h>
#include<sys/msg.h>
#define BUFSIZE 1024
struct msg_st
{
int msg_type;
char msg_buf[BUFSIZE];
};
int main(int argc, char *argv[])
{
int msgid;//定义消息队列id
key_t key;//唯一识别两通信的消息队列,要与接收方一致
struct msg_st msg_data;
char buffer[BUFSIZE];
int runnig = 1;
//消息队列是否创建成功
if((msgid = msgget(key = 1234, 0666 | IPC_CREAT)) == -1)
{
fprintf(stderr, "msgget failed with error:%d\n",errno);
exit(-1);
}
while(runnig)
{
//get some data
printf("enter some data:");
fgets(buffer,BUFSIZE,stdin);
msg_data.msg_type = 1;
strcpy(msg_data.msg_buf,buffer);
//send data
if(msgsnd(msgid, (void *)&msg_data, BUFSIZE, 0) == -1)
{
fprintf(stderr, "msgsend failed with error:%d\n",errno);
exit(-1);
}
//exit with end
if(strncmp(msg_data.msg_buf,"end",3) == 0)
{
runnig = 0;
}
}
if(msgctl(msgid,IPC_RMID,0) == -1)
{
fprintf(stderr, "msgctl failed with error:%d\n",errno);
exit(-1);
}
exit(0);
}
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<unistd.h>
#include<sys/msg.h>
#define BUFSIZE 1024
struct msg_st
{
int msg_type;
char msg_buf[BUFSIZE];
};
int main(int argc, char *argv[])
{
int msgid;
key_t key;
struct msg_st msg_data;
int msg_recv = 0;
int runnig = 1;
if((msgid = msgget(key = 1234, 0666 | IPC_CREAT)) == -1)
{
fprintf(stderr, "msgget failed with error:%d\n",errno);
exit(-1);
}
while(runnig)
{
if(msgrcv(msgid, (void *)&msg_data, BUFSIZE, msg_recv, 0) == -1)
{
fprintf(stderr, "msgrcv failed with error:%d\n",errno);
exit(-1);
}
//以end结束
printf("receive data: %s\n",msg_data.msg_buf);
if(strncmp(msg_data.msg_buf,"end",3) == 0)
{
runnig = 0;
}
}
//关闭消息队列
if(msgctl(msgid,IPC_RMID,0) == -1)
{
fprintf(stderr, "msgctl failed with error:%d\n",errno);
exit(-1);
}
exit(0);
}
1.定义一个结构体用来存放数据,msg_data和msg_type
2.定义消息队列id,创建消息队列 msgget(){}
3.消息队列接收和发送函数 msgrcv(){}和 msgsnd(){}
4.关闭消息队列 msgctl(){}
注意:在定义key_t key 的时候,发送和接收的key值要相同