1、消息队列函数的使用
“消息队列”是在消息的传输过程中保存消息的容器。当消息从队列内取出后,相应的消息就从队列中删除了。
(1)ftok获得唯一的key值
key_t ftok(const char *pathname, int proj_id);
pathname就是你指定的文件名(已经存在的文件名),一般使用当前目录
proj_id就是你指定的id值
(2)msgget用于创建一个新的或打开一个已经存在的消息队列,此消息队列与key相对应。
int msgget(key_t key, int msgflg);
key:函数ftok的返回值或IPC_PRIVATE。
msgflag: IPC_CREAT:创建新的消息队列。
IPC_EXCL:与IPC_CREAT一同使用,表示如果要创建的消息队列已经存在,则返回错误。
IPC_NOWAIT:读写消息队列要求无法满足时,不阻塞。返回值: 调用成功返回队列标识符,否则返回-1.
(3)msgsnd发送队列消息‘
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
(4)msgrcv接收队列消息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
第五个参数msgflg依然是是控制函数行为的标志。
0:默认行为,如果消息队列没有内容,则等待。
IPC_NOWAIT:如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数 的进程。如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件的 消息为止。如果一个client 正在等待消息的时候队列被删除,EIDRM 就会被返回。如果进 程在阻塞等待过程中收到了系统的中断信号,EINTR 就会被返回。
MSG_NOERROR:如果函数取得的消息长度大于msgsz,将只返回msgsz 长度的信息, 剩下的部分被丢弃了。如果不指定这个参数,E2BIG 将被返回,而消息则留在队列中不被取出。
2、Linux C代码实现消息队列
发送消息:
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
typedef struct stMsgQueue
{
long nMsgType;
char szMsgBody[BUFSIZ];
}MSG_QUEUE;
int main()
{
int nMsgId = 0;
MSG_QUEUE stSendMsg = {'b',"hello"};
nMsgId = msgget(ftok("/home/nii/",1000),IPC_CREAT);
if(-1 == nMsgId)
{
perror("get nMsgId failed : ");
return 1;
}
/** 发送消息 */
if(-1 == msgsnd(nMsgId,&stSendMsg,6,0))
{
perror("send message failed\n");
return 1;
}
return 0;
}
接收队列消息:
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
typedef struct stMsgQueue
{
long nMsgType;
char szMsgBody[BUFSIZ];
}MSG_QUEUE;
int main()
{
int nMsgId = 0;
MSG_QUEUE stSendMsg;
nMsgId = msgget(ftok("/home/nii/",1000),IPC_CREAT);
if(-1 == nMsgId)
{
perror("get nMsgId failed : ");
return 1;
}
/** 接收消息 */
if(-1 == msgrcv(nMsgId,&stSendMsg,BUFSIZ,'b',IPC_NOWAIT))
{
perror("receive message failed: ");
return 1;
}
printf("%s\n",stSendMsg.szMsgBody);
return 0;
}