人们常说迈出第一步是最难的,第一次在网上写文章,有种剪不断理还乱的感觉,但作为自
己平常工作和学习的积累,迈出这一步是值得的。其中不乏汲取网上优秀文章的精髓,希望诸
位前辈多多指教,小生必将感激不尽!
消息队列,顾名思议,就是一个消息的列表,用户可以从消息队列中添加信息,读取消息等。
消息队列的实现包括创建和打开消息队列,添加消息,读取消息,控制消息队列这四种操作。
(1) 创建和打开消息队列
消息队列的内核持续性要求每个消息队列都在系统范围内对应唯一的键值,因此,消息队列描
述字是由在系统范围内唯一的键值生成的,而键值可以看作对应系统内的一条路经。
1> int msgget(key_t key, int msgflg);
参数key是一个键值,由ftok获得,msgflg参数是一些标志位。该调用返回与健值key相对
应的消息队列描述字。
在以下两种情况下,该调用将创建一个新的消息队列:
i:如果没有消息队列与健值key相对应,并且msgflg中包含了IPC_CREAT标志位;
ii:key参数为IPC_PRIVATE;
参数msgflg可以为以下:IPC_CREAT、IPC_EXCL、IPC_NOWAIT或三者的或结果。
调用返回 :成功返回消息队列描述字,否则返回-1。
2> key_t ftok (char*pathname, char proj);
它返回与路径pathname相对应的一个键值.
上面两个函数用在一起,最常用法:
int msgid;
msgid = msgget(ftok("/etc", 2), IPC_CREAT|00666);
(2) 向消息队列中添加消息
int msgsnd(int msgid, struct msgbuf *msgp, int msgsz, int msgflg);
向msgid代表的消息队列发送一个消息,即将发送的消息存储在msgp指向的msgbuf结构
中,消息的大小由msgze指定。
每个消息都有类似如下的结构:
struct msgbuf{
long msgtype;
char msgdata[1024];
}
对发送消息来说,有意义的msgflg标志为IPC_NOWAIT,指明在消息队列没有足够空间容纳
要发送的消息时,msgsnd是否等待。
造成msgsnd()等待的条件有两种:
1> 当前消息的大小与当前消息队列中的字节数之和超过了消息队列的总容量;
2> 当前消息队列的消息数(单位"个")不小于消息队列的总容量(单位"字节数"),此时,
虽然消息队列中的消息数目很多,但基本上都只有一个字节。
msgsnd()解除阻塞的条件有三个:
1> 不满足上述两个条件,即消息队列中有容纳该消息的空间;
2> msgid代表的消息队列被删除;
3> 调用msgsnd()的进程被信号中断;
调用返回:成功返回0,否则返回-1。
(3) 从消息队列中读取消息
int msgrcv(int msgid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg);
从msgid代表的消息队列中读取消息,存储到msgp所指向的msgbuf中。
msgtyp 代表消息的字节数。msgflg 一般默认为0;
调用返回:成功返回读取消息的字节数,否则返回-1。
下面举实际应用中的简单例子:
/* server.c */
从终端得到信息,写入消息队列。
#include<stdio.h> #include<stdlib.h> #include<netinet/in.h> #include<sys/types.h> #include<string.h> #include<sys/ipc.h> #include<errno.h> #include<sys/stat.h> #include<unistd.h> #include<sys/msg.h>
typedef struct sysmess { long msgtype; char msgdata[1024]; }message; int main() { int msgid; message mess; mess.msgtype = 1; bzero(mess.msgdata, sizeof(mess.msgdata)); if((msgid = msgget(ftok("/etc", 2), IPC_CREAT|00666)) == -1) { perror("msgget"); exit(0); } while(1){ printf("input msg ..."); scanf("%s", mess.msgdata); printf("mess.msgdata :%s\n",mess.msgdata); if(msgsnd(msgid, &mess, strlen(mess.msgdata),0) == -1) { perror("msgsnd"); exit(0); } } }
|
/*client.c*/
从消息队列读取消息,打印在终端。
#include<stdio.h> #include<stdlib.h> #include<netinet/in.h> #include<sys/types.h> #include<string.h> #include<sys/ipc.h> #include<errno.h> #include<sys/stat.h> #include<unistd.h> #include<sys/msg.h>
typedef struct sysmess { long msgtype; char msgdata[1024]; }message; int main() { int msgid; message mess; mess.msgtype = 1; if((msgid = msgget(ftok("/etc", 2), IPC_CREAT|00666)) == -1) { perror("msgget"); exit(0); } while(1) { bzero(mess.msgdata, sizeof(mess.msgdata)); if(msgrcv(msgid, &mess, sizeof(mess.msgdata),0, 0) == -1) { perror("msgrcv"); exit(0); } printf("receive msg from server : %s\n",mess.msgdata); } }
|
阅读(3116) | 评论(0) | 转发(0) |