消息队列
消息队列是基于消息的,且读取方式不一定是FIFO;
消息队列提供了一种从一个进程向另一个进程发送一个有类型数据块的方法;
消息队列可以实现双向通信;
消息队列是用链表实现的;
消息队列数据结构 :
struct msqid_ds {
struct ipc_perm msg_perm; /* Ownership and permissions */
time_t msg_stime; /* Time of last msgsnd(2) */
time_t msg_rtime; /* Time of last msgrcv(2) */
time_t msg_ctime; /* Time of last change */
unsigned long __msg_cbytes; /* Current number of bytes in
queue (non-standard) */
msgqnum_t msg_qnum; /* Current number of messages
in queue */
msglen_t msg_qbytes; /* Maximum number of bytes
allowed in queue */
pid_t msg_lspid; /* PID of last msgsnd(2) */
pid_t msg_lrpid; /* PID of last msgrcv(2) */
};
内核为每一个IPC对象维护一个结构体数据结构。
IPC对象数据结构:
struct ipc_perm {
key_t __key; /* Key supplied to msgget(2) */
uid_t uid; /* Effective UID of owner */
gid_t gid; /* Effective GID of owner */
uid_t cuid; /* Effective UID of creator */
gid_t cgid; /* Effective GID of creator */
unsigned short mode; /* Permissions */
unsigned short __seq; /* Sequence number */
};
(一)创建消息队列
int msgget(key_t key,int msgflag);
(1)参数:
ket_t key = ftok(const char* pathname,int proj_id);
int msgflag=(1) IPC_CREAT //当这个消息队列不存在时创建,当所创建的消息队列存在时打开该消息队列;
(2) IPC_CREAT | IPC_EXCL //当所创建的消息队列不存在时创建,当所创建的消息队列存在时,出错返回;
(2)返回值:
msgget函数的返回值为消息队列的标识符,类似于文件描述符;
(二)给消息队列发送数据
int msgsnd(int msgid,const char* msgp,ssize_t msgsz,int msgflag);
(1)参数:
msgid:为msgget的返回值,消息队列标识符;
msgp:为一个结构体数据结构:
struct msgbuf
{
long mtype; //数据块的类型
char mtext[1]; //数据块,可来自定义自己要发送数据块的大小;
};
msgsz:struct msgbuf 中mtext的大小----------sizeof(mtext);
msgflag: 0表示以阻塞的方式进行数据发送;
(2)返回值:
1)返回-1表示调用失败;
2)如果调用成功,则返回发送数据的字节数;
(三)接收消息队列中的数据
(1)参数:
ssize_t msgrcv(int msgid,void *msgp,ssize_t msgsz,long msgtyp,int msgflag);
msgid:接收哪一个消息队列的数据,消息队列标识符;
msgp:存放数据的缓冲区;
msgsz:接收数据缓冲区的大小;
msgtyp:所接收的数据的类型;
msgflag:0表示以阻塞的方式接收数据;
(2)返回值:
失败返回-1;
成功返回接收到数据的字节数;
(四)删除消息队列
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
(1)参数:
msgid:消息队列标识符,表示要删除哪一个消息队列;
cmd:IPC_RMID表示删除;
buf:NULL
(2)返回值:
删除成功返回0;
删除失败返回-1;
common.h
#ifndef _COMMON_H
#define _COMMON_H
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
#include<unistd.h>
#define PATHNAME "/home/cm/code"
#define PROJ_ID 0x6666
#define SERVER_TYPE 1
#define CLIENT_TYPE 2
struct msgbuf
{
long mtype;
char mtext[1024];
};
int commonCreat_messageQueue(int flags);
int Get_messageQueue();
int Creat_messageQueue();
int Delete_messageQueue(int msg_id);
int sendData_To_messageQueue(int msg_id,int sendType,char* msg);
int receiveData_Of_messageQueue(int msg_id,int recvType,char *out);
#endif
common.c
#include"common.h"
int commonCreat_messageQueue(int flags)
{
key_t key = ftok(PATHNAME,PROJ_ID);
if(key < 0)
{
perror("ftok");
return -1;
}
int msg_id = msgget(key,flags);
if(msg_id < 0)
{
perror("msgget");
return -2;
}
return msg_id;
}
int Creat_messageQueue()
{
int msg_id = commonCreat_messageQueue(IPC_CREAT | IPC_EXCL|0666);
return msg_id;
}
int Get_messageQueue()
{
int msg_id = commonCreat_messageQueue(IPC_CREAT);
return msg_id;
}
int Delete_messageQueue(int msg_id)
{
if( msgctl(msg_id,IPC_RMID,NULL)<0)
{
return -1;
}
return 0;
}
//send data
int sendData_To_messageQueue(int msg_id,int sendType,char* msg)
{
struct msgbuf buf;
buf.mtype = sendType;
strcpy(buf.mtext,msg);
int snd_msg = msgsnd(msg_id,(void*)&buf,sizeof(buf.mtext),0);
if(snd_msg <0)
{
perror("msgsng");
return -3;
}
return 0;;
}
//receive data
int receiveData_Of_messageQueue(int msg_id,int recvType,char* out)
{
struct msgbuf buf;
ssize_t s = msgrcv(msg_id,(void*)&buf,sizeof(buf.mtext),recvType,0);
if(s < 0)
{
perror("msgrcv");
return -4;
}
strcpy(out,buf.mtext);
return 0;
}
server.c
//server-------------first receive data and next to send data
#include"common.h"
int main()
{
char buf[1024];
int msg_id = Creat_messageQueue();
while(1)
{
//receive data
receiveData_Of_messageQueue(msg_id,CLIENT_TYPE,buf);
printf("Client#%s\n",buf);
//send data
printf("Please Enter# ");
fflush(stdout);
ssize_t s = read(0,buf,sizeof(buf)-1);
if(s>0) //read success
{
buf[s-1] = 0;
sendData_To_messageQueue(msg_id,SERVER_TYPE,buf);
printf("send done,wait receive........\n");
}
}
return 0;
Delete_messageQueue(msg_id);
}
client.c
//client---------------first send data and next is to receive data
#include"common.h"
int main()
{
int msg_id = Get_messageQueue();
//read data from stdin and send to msgqueue
char buf[1024];
while(1)
{
printf("Please Enter# ");
fflush(stdout);
ssize_t s = read(0,buf,sizeof(buf)-1);
if(s<0)
{
//read failed
perror("read");
}
buf[s-1] = 0;
sendData_To_messageQueue(msg_id,CLIENT_TYPE,buf);
printf("send done,wait receive............\n");
receiveData_Of_messageQueue(msg_id,SERVER_TYPE,buf);
printf("Server# %s\n",buf);
}
return 0;
}
Makefile:
.PHONY:all
all:client server
client:client.c common.c
gcc -o $@ $^
server:server.c common.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -rf server client
作者水平有限,若有问题,请留言,谢谢!!!