




已阅读5页,还剩4页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
QQ: 9 作者:叶建敏 4/29/2020 在linux系统下消息队列的聊天室实现的过程:1.消息队列消息队列是消息的链接表,存放在内核中并由消息队列标识符标识。我们将称消息队列为“队列”,其标识符为“队列I D”。m s g g e t用于创建一个新队列或打开一个现存的队列。m s g s n d用于将新消息添加到队列尾端。每个消息包含一个正长整型类型字段,一个非负长度以及实际数据字节(对应于长度),所有这些都在将消息添加到队列时,传送给m s g s n d。m s g r c v用于从队列中取消息。我们并不一定要以先进先出次序取消息,也可以按消息的类型字段取消息。每个队列都有一个m s q i d d s结构与其相关。此结构规定了队列的当前状态。如图(1-1)图(1-1)msqid_ds结构调用的第一个函数通常是m s g g e t,其功能是打开一个现存队列或创建一个新队列。#include #include #include int msgget(key_t key, int flag) ;返回:若成功则为消息队列I D,若出错则为- 1调用m s g s n d将数据放到消息队列上。#include #include #include int msgsnd(int msqid, const void * pt r, size_tnbytes, int flag) ;返回:若成功则为0,若出错则为- 1正如前面提及的,每个消息都由三部分组成,它们是:正长整型类型字段、非负长度(nbytes)以及实际数据字节(对应于长度)。消息总是放在队列尾端。ptr指向一个长整型数,它包含了正整型消息类型,在其后立即跟随了消息数据。(若nbytes是0,则无消息数据。)若发送的最长消息是5 1 2字节,则可定义下列结构:struct mymesg long mtype; /* positive message type */char mtext512; /* message dat,aof length n b y t e s * / ;于是,p t r就是一个指向mymesg结构的指针。接收者可以使用消息类型以非先进先出的次序取消息。f l a g的值可以指定为IPC_NOWAIT。这类似于文件I / O的非阻塞I / O标志。若消息队列已满(或者是队列中的消息总数等于系统限制值,或队列中的字节总数等于系统限制值),则指定IPC_NOWAIT使得msgsnd立即出错返回EAGAIN。如果没有指定IPC_NO WAIT,则进程阻塞直到(a)有空间可以容纳要发送的消息,或( b)从系统中删除了此队列,或( c)捕捉到一个信号,并从信号处理程序返回。在第二种情况下,返回E I D R M(“标志符被删除”)。最后一种情况则返回E I N T R。注意,对消息队列删除的处理不是很完善。因为对每个消息队列并没有设置一个引用计数器(对打开文件则有这种计数器),所以删除一个队列使得仍在使用这一队列的进程在下次对队列进行操作时出错返回。信号量机构也以同样方式处理其删除。删除一个文件则要等到使用该文件的最后一个进程关闭了它,才能删除文件的内容。msgrcv从队列中取用消息。#include #include #include int msgrcv(intm s q i d, void *ptr, size_t nbytes, long type, int flag) ;返回:若成功则为消息数据部分的长度,若出错则为- 1如同msgsnd中一样,p t r参数指向一个长整型数(返回的消息类型存放在其中),跟随其后的是存放实际消息数据的缓存。nbytes说明数据缓存的长度。若返回的消息大于nbytes,而且在f l a g中设置了MSGNOERROR,则该消息被截短(在这种情况下,不通知我们消息截短了)。如果没有设置这一标志,而消息又太长,则出错返回E2BIG(消息仍留在队列中)。参数type使我们可以指定想要哪一种消息:type = 0 返回队列中的第一个消息。type 0 返回队列中消息类型为t y p e的第一个消息。type 0 返回队列中消息类型值小于或等于t y p e绝对值,而且在这种消息中,其类型值又最小的消息。非0t y p e用于以非先进先出次序读消息。例如,若应用程序对消息赋优先权,那么t y p e就可以是优先权值。如果一个消息队列由多个客户机和一个服务器使用,那么t y p e字段可以用来包含客户机进程I D。可以指定flag值为IPC_NOWAIT,使操作不阻塞。这使得如果没有所指定类型的消息,则msgrcv出错返回ENOMSG。如果没有指定IPC _NOWAIT,则进程阻塞直至(a)有了指定类型的消息,或(b)从系统中删除了此队列(出错返回E I D R M),或(c)捕捉到一个信号并从信号处理程序返回(出错返回E I N T R)。实例一消息队列与流管道的时间比较如若需要客户机和服务器之间的双向数据流,可以使用消息队列或流管道。2.简单的消息队列聊天列子。/*服务端的代码*/*server.c*/*作者:叶建敏*/*QQ:*/#include #include #include #include #include #include /以上为程序所必须的头文件struct msgbuf long mtype; /消息类型char mtext100; /消息正文;/定义一个结构体msgbuf用来存放消息的类型和消息的正文int main()FILE *fp; /定义文件变量指针key_t key; pid_t pid;int msgid; /队列ID号struct msgbuf msg1,msg2; /定义两个结构体变量char wbuf800=,my_name20=,others_name20=; / 消息内容,本地名字,对方名字key=ftok(.,0xFF); /调用ftok函数,产生标准的keyif(msgid=msgget(key,IPC_CREAT|0666)0) /调用msgget函数,创建和打开消息队列perror(msgger error); exit(0);printf(plese input you name:);msg1.mtype=3; /消息类型为3,此消息接受让对方对方接受的对应的消息类型的姓名memset(msg1.mtext,0,100);/ 设置缓冲区的内容fgets(wbuf,100,stdin);/将标准输入到wbuf缓冲区wbufstrlen(wbuf)-1=0;strcpy(my_name,wbuf);/把wbuf里的内容复制到my_namestrcpy(msg1.mtext,wbuf);/msgsnd(msgid,&msg1,sizeof(msg1.mtext),0);/把消息添加到消息队列中msgrcv(msgid,&msg2,100,4,0);/根据消息队列的消息类型接受对应的消息对方的姓名strcpy(others_name,msg2.mtext);/根据上面获得的数据把对方的的名字存储到others_name,存储是根据消息号存储fflush(stdout);if(pid=fork()0)/创建一个子进程printf(erro);exit(0);if(pid=0)while(1)msg1.mtype=1;memset(msg1.mtext,0,100);/刷新printf(%s:,my_name);fgets(wbuf,100,stdin);wbufstrlen(wbuf)-1=0;strcpy(msg1.mtext,wbuf);msgsnd(msgid,&msg1,sizeof(msg1.mtext),0);elsewhile(1)msgrcv(msgid,&msg2,100,2,0);if(fp=fopen(data.txt,a+)=NULL)perror(打开失败记录);return 0;fprintf(fp,%s:%sn,others_name,msg2.mtext);fclose(fp);printf(r%s:%sn%s:,others_name,msg2.mtext,my_name);fflush(stdout);/*哭护短的代码*/*client.c*/*作者:叶建敏*/*QQ:*/#include #include #include #include #include #include struct msgbuflong mtype; /消息类型char mtext100; /消息正文;int main()FILE *fp;key_t key;pid_t pid;int msgid; /队列IDstruct msgbuf msg1,msg2;char wbuf800=,my_name20=,others_name20=;key=ftok(.,0xFF);if(msgid=msgget(key,IPC_CREAT|0666)0)/创建队列perror(msgger error);exit(0);printf(plese input you name:);msg1.mtype=4; /消息类型为3,此消息接受对方的姓名memset(msg1.mtext,0,100);/ 设置缓冲区的内容fgets(wbuf,100,stdin);/将标准输入到wbuf缓冲区wbufstrlen(wbuf)-1=0;strcpy(msg1.mtext,wbuf);strcpy(my_name,wbuf);msgsnd(msgid,&msg1,sizeof(msg1.mtext),0);msgrcv(msgid,&msg2,100,3,0);strcpy(others_name,msg2.mtext);fflush(stdout);if(pid=fork()0)printf(erro);exit(0);if(pid=0)while(1)msgrcv(msgid,&msg2,100,1,0);if(fp=fopen(data.txt,a+)=NULL)perror(打开失败记录);return 0;fprintf(fp,%s:%sn,others_name,msg2.mtext);fclose(fp);printf(r%s:%sn%s:,others_name,msg2.mtext,my_name);fflush(stdout);elsewhile(1)msg1.mtype=2;memset(msg1.mtext,0,100);/刷新printf(%s:,my_name);fgets(wbuf,100,stdin);wbufstrlen(wbuf)-1=0;strcpy(msg1.mtext,wbuf);msgsnd(msgid,&msg1,sizeof(msg1.mtext),0);3.消息队列小例子#include #include #include #include #include #include #include void msg_show_attr(int msg_id,struct msqid_ds msg_info)int ret=-1;sleep(1);ret=msgctl(msg_id,IPC_STAT,&msg_info);if(ret=-1)printf(get message wrong!n);exit(1);printf(n);printf(now the crow word number is :%dn,msg_info.msg_cbytes);printf(the message number is:%dn,msg_info.msg_qnum);printf(the crow max number is:%dn,msg_info.msg_qbytes);printf(the last messages pid is :%dn,msg_info.msg_lspid);printf(the last receve meassages pid is:%d,msg_info.msg_lrpid);printf(the last send time is:%s,ctime(&(msg_info.msg_stime);printf(the last receve time is:%s,ctime(&(msg_info.msg_rtime);printf(the last changed time is:%s,ctime(&(msg_info.msg_ctime);printf(the message UID is :%dn,msg_info.msg_perm.uid);printf(the message GID is :%dn,msg_info.msg_perm.gid);int main()int ret=-1;int msg_flags,msg_id;key_t key;struct msgmbufint mtype;char mtext20;struct msqid_ds msg_info;struct msgmbuf msg_mbuf; struct msgmbuf msg_mbuf1; struct msgmbuf msg_mbuf2;int msg_sflags,msg_rflags;char *msgpath=/home/yejianmin/;key=ftok(msgpath,f);if(key!=-1)printf(成功创建!n);elseprintf(KEY失败);msg_flags=IPC_CREAT;msg_id=msgget(key,msg_flags|0x0777);if(msg_id=-1)printf(found message error;n);return 0;msg_show_attr(msg_id,msg_info);msg_sflags=IPC_NOWAIT;msg_mbuf.mtype=1;msg_mbuf1.mtype=2;msg_mbuf2.mtype=3;memcpy(msg_mbuf.mtext,测试消息,sizeof(测试消息);ret =msgsnd(msg_id,&msg_mbuf,sizeof(测试消息),msg_sflags);memcpy(msg_mbuf1.mtext,测试消息1,sizeof(测试消息1); ret = msgsnd(msg_id,&msg_mbuf1,sizeof(测试消息),msg_sflags); memcpy(msg_mbuf2.mtext,测试消息2,sizeof(测试消息2); ret = msgsnd(msg_id,&msg_mbuf2,sizeof(测试消息),msg_sflags);printf(msg_mbuf.mtext=%sn,msg_mbuf.mtext);printf(msg_mbuf1.mtext=%sn,msg_mbuf1.m
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年临沂市工程学校公开招聘教师(10名)模拟试卷及答案详解(名校卷)
- 班组安全学习培训记录课件
- 2025广西南宁市水利局编制外工作人员招聘1人模拟试卷附答案详解(黄金题型)
- 2025广西西林县委员会社会工作部招聘专职化社区工作者(专职网格管理员)编外聘用人员8人考前自测高频考点模拟试题及1套参考答案详解
- 班组安全培训记录评价课件
- 2025吉林二道江区政府专职消防员招聘1人模拟试卷及一套答案详解
- 2025包头市东河区机关所属事业单位春季引进人才51人模拟试卷及参考答案详解
- 2025甘肃陇南市成县招聘城镇公益性岗位人员16人考前自测高频考点模拟试题及答案详解(考点梳理)
- 2025年福建省级机关医院招聘10人考前自测高频考点模拟试题及一套完整答案详解
- 2025广西临桂农村商业银行劳务派遣人员招聘4人考前自测高频考点模拟试题及答案详解(网校专用)
- 2025年郑州航空港经济综合实验区招聘社区工作人员120名考试参考题库附答案解析
- (2025年标准)桑叶收购协议书
- 2025年建筑工程项目管理综合能力测评题库(附答案)
- 儿科哮喘护理个案
- 电力设备质量管理方案及保证措施
- 陪诊培训课件
- 2025至2030年中国工业控制软件行业市场运行态势及前景战略研判报告
- 2024年12月27日山西省临汾市纪委遴选面试真题及答案解析
- 2025年数智供应链案例集-商务部
- 艺术漆涂料施工合同协议
- 陈皮种植转让合同协议
评论
0/150
提交评论