System V 消息队列
2016-05-18 21:26
447 查看
首先我们来看操纵System V消息队列的函数。
(1)msgget函数用于创建一个新的消息队列或访问一个已存在的消息队列
#include<sys/msg.h>
int msgget(key_t key,int oflag);
返回值是一个整数标识符。它是基于指定的key值产生的,而key即可以是ftok的返回值,也可以是常值IPC_PRIVATE.
![](http://img.blog.csdn.net/20160517213854027)
oflag表示读写权限值的组合。
![](http://img.blog.csdn.net/20160517213813683)
(2)msgsnd函数:
使用msgget函数打开一个消息队列后,我们使用msgsnd往其上放置一个消息
#include<sys/msg.h>
int msgsnd(int msqid,const void *ptr,size_t length,int flag)
其中msqid是由msgget返回的标识符。ptr是一个结构指针,该结构具有如下的模板:
struct msgbuf{
long mtype;
char mtext[1];
};
length参数以字节为单位指定待发消息的长度。这是位于长整数消息之后的用户自定义数据的长度。该长度可以是0.
flag参数即可以是0,也可以是IPC_NOWAIT。IPC_NOWAIT标志使得msgsnd调用非阻塞:如果没有存放新消息的可用空间,该函数就马上返回。
(3)msgrev函数:
使用msgrev函数从某一个消息队列中读出一个消息。
#include<sys/msg.h>
ssize_t msgrev(int msqid,void *ptr,size_t length,long type,int flag)
其中ptr参数指定所接收的消息存放的位置,
length指定了由ptr指向的缓冲区中的数据部分的大小。这是该函数能返回的最大数据量。该长度不包括长整型类型字段。
type指定希望从所给定的队列中读取什么样的消息:
(1)如果type为0,那就返回该队列中的第一个消息。
(2)如果type大于0,那就返回其类型值为type的第一个消息。
(3)如果type小于0,那就返回其类型值小于或等于type参数的绝对值的消息中类型值最小的第一个参数。
(4)msgctl函数:
提供在一个消息队列上的各种控制操作。
#include<sys/msg.h>
int magctl(int msqid,int cmd,struct misqid_ds *buff)
返回:成功为0,错误为-1
现在我们用消息队列实现客户端-服务器的例子,服务器获得路径名,将文件的内容返回到客户端。
我们先来看客户端的程序:
服务器程序:
头文件加一些函数 uitil.h
我们在命令行启动服务器,然后再启动客户端,其执行结果如下:
![](http://img.blog.csdn.net/20160518212449896)
第一种情况为test文件存在时,服务器将文件的返回到客户端。
第二种情况为文件不存在时,服务器将返回错误。。。。
(1)msgget函数用于创建一个新的消息队列或访问一个已存在的消息队列
#include<sys/msg.h>
int msgget(key_t key,int oflag);
返回值是一个整数标识符。它是基于指定的key值产生的,而key即可以是ftok的返回值,也可以是常值IPC_PRIVATE.
oflag表示读写权限值的组合。
(2)msgsnd函数:
使用msgget函数打开一个消息队列后,我们使用msgsnd往其上放置一个消息
#include<sys/msg.h>
int msgsnd(int msqid,const void *ptr,size_t length,int flag)
其中msqid是由msgget返回的标识符。ptr是一个结构指针,该结构具有如下的模板:
struct msgbuf{
long mtype;
char mtext[1];
};
length参数以字节为单位指定待发消息的长度。这是位于长整数消息之后的用户自定义数据的长度。该长度可以是0.
flag参数即可以是0,也可以是IPC_NOWAIT。IPC_NOWAIT标志使得msgsnd调用非阻塞:如果没有存放新消息的可用空间,该函数就马上返回。
(3)msgrev函数:
使用msgrev函数从某一个消息队列中读出一个消息。
#include<sys/msg.h>
ssize_t msgrev(int msqid,void *ptr,size_t length,long type,int flag)
其中ptr参数指定所接收的消息存放的位置,
length指定了由ptr指向的缓冲区中的数据部分的大小。这是该函数能返回的最大数据量。该长度不包括长整型类型字段。
type指定希望从所给定的队列中读取什么样的消息:
(1)如果type为0,那就返回该队列中的第一个消息。
(2)如果type大于0,那就返回其类型值为type的第一个消息。
(3)如果type小于0,那就返回其类型值小于或等于type参数的绝对值的消息中类型值最小的第一个参数。
(4)msgctl函数:
提供在一个消息队列上的各种控制操作。
#include<sys/msg.h>
int magctl(int msqid,int cmd,struct misqid_ds *buff)
返回:成功为0,错误为-1
现在我们用消息队列实现客户端-服务器的例子,服务器获得路径名,将文件的内容返回到客户端。
我们先来看客户端的程序:
#include"uitil.h" int main(int argc,char* argv[]) { int readid,writeid; writeid = msgget(MQ_KEY1,0); if(writeid == -1){ cout << "writeid error." << endl; exit(1); } readid = msgget(MQ_KEY2,0); if(readid == -1){ cout << "readid error." << endl; exit(1); } client(readid,writeid); msgctl(readid,IPC_RMID,NULL); msgctl(writeid,IPC_RMID,NULL); return 0; }
服务器程序:
#include"uitil.h" int main(int argc,char*argv[]) { int readid,writeid; readid = msgget(MQ_KEY1,SVMSG_MODE | IPC_CREAT); if(readid == -1){ cout << "readid msgget error." << endl; exit(1); } writeid = msgget(MQ_KEY2,SVMSG_MODE | IPC_CREAT); if(writeid == -1){ cout << "writeid msgget error." << endl; exit(1); } server(readid,writeid); return 0; }
头文件加一些函数 uitil.h
#pragma once #include<iostream> #include<stdio.h> #include<sys/msg.h> #include<string.h> #include<stdlib.h> #include<unistd.h> #include<errno.h> using namespace std; #define MQ_KEY1 1234L #define PIPE_BUFF 4096 #define MQ_KEY2 2345L #define MAXMESGDATA (PIPE_BUFF - 2 * sizeof(long)) #define MESGHDRSIZE (sizeof(struct mymesg) - MAXMESGDATA) #define MSG_R 0400 //read permission #define MSG_W 0200 //write permission #define SVMSG_MODE (MSG_R | MSG_W | MSG_R >> 3 | MSG_R >> 6) struct mymesg{ long mesg_len; long mesg_type; char mesg_data[MAXMESGDATA]; }; ssize_t mesg_send(int id,struct mymesg *mptr) { return (msgsnd(id,&(mptr->mesg_type),mptr->mesg_len,0)); } ssize_t mesg_recv(int id,struct mymesg *mptr) { ssize_t n; n = msgrcv(id,&(mptr->mesg_type),MAXMESGDATA,mptr->mesg_type,0); mptr->mesg_len = n; return (n); } void client(int readfd,int writefd) { size_t len; ssize_t n; struct mymesg mesg; //将客户端输入的路径名写入mesg.mesg_data中 fgets(mesg.mesg_data,MAXMESGDATA,stdin); len = strlen(mesg.mesg_data); if(mesg.mesg_data[len - 1] == '\n'){ len--; } mesg.mesg_len = len; mesg.mesg_type = 1; //将mesg的内容放入队列MQ_KEY1 mesg_send(writefd, &mesg); //客户端从MQ_KEY2中读出文件的内容进行显示 while((n = mesg_recv(readfd,&mesg)) > 0){ write(STDOUT_FILENO,mesg.mesg_data,n); } } void server(int readfd,int writefd) { FILE *fp; ssize_t n; struct mymesg mesg; mesg.mesg_type = 1; //服务器从MQ_KEY1队列中的消息读入到mesg中 //其中mesg为路径名 if((n = mesg_recv(readfd,&mesg)) == 0){ cout << "pathname missing." << endl; exit(1); } mesg.mesg_data = '\0'; if((fp = fopen(mesg.mesg_data,"r")) == NULL){ snprintf(mesg.mesg_data + n,sizeof(mesg.mesg_data) - n, ": cant't open,%s\n",strerror(errno)); mesg.mesg_len = strlen(mesg.mesg_data); mesg_send(writefd,&mesg); }else{ //当以只读方式打开文件成功时,将文件的内容放入队列MQ_KEY2 while(fgets(mesg.mesg_data,MAXMESGDATA,fp) != NULL){ mesg.mesg_len = strlen(mesg.mesg_data); mesg_send(writefd,&mesg); } fclose(fp); } mesg.mesg_len = 0; mesg_send(writefd,&mesg); }
我们在命令行启动服务器,然后再启动客户端,其执行结果如下:
第一种情况为test文件存在时,服务器将文件的返回到客户端。
第二种情况为文件不存在时,服务器将返回错误。。。。
相关文章推荐
- 媒体和资源
- 逆向分析 Android 程序
- git与github安装、配置、pull、push
- css样式汇总(转载)
- win10运行慢的解决
- Maven的作用
- 1003 Problem C
- [弦图 最小染色 完美消除序列 MCS算法] BZOJ 1006 [HNOI2008]神奇的国度
- 格式化标签
- c的调试
- POJ 3233 Matrix Power Series (矩阵快速幂/等比矩阵)
- android apk安装到模拟器 不显示
- NYOJ 题目716 River Crossing
- OC 对象整合练习题
- 区间动规经典(水题)大合集
- 归并排序算法(排序详解)
- THUCTC源码解读(二)
- 【HYSBZ 1503: [NOI2004]】郁闷的出纳员——伸展树
- 练习打字第十一天!
- 使用jetty-maven-plugin插件进行测试