ImageVerifierCode 换一换
格式:DOCX , 页数:46 ,大小:280.82KB ,
资源ID:11496158      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/11496158.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(网络编程聊天程序设计文档.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

网络编程聊天程序设计文档.docx

1、网络编程聊天程序设计文档此文档为网络编程课程设计文档。课程设计题目:网络编程聊天程序程序运行环境:Ubuntu Linux编程语言:C语言使用图形界面技术:GTK+2.0本人是大学本科生,所学知识有限,在此班门弄虎了,希望与大家在技术上多多交流。此文所有权归本人所有,所以请勿抄袭。网络编程聊天程序设计报告学 院:计算机与电子信息学院专业名称:网络工程姓 名:网名:书箱子时 间:2011年1月聊天程序设计任务书1.设计题目自己设计应用层协议,实现聊天程序,要求能够实现服务器能够同时处理多个客户的连接请求,实现客户端通过服务器的转发通信。2. 实验设计2.1 实验环境1)虚拟机:Oracle VM

2、 VirtualBox2)操作系统:Ubuntu-10.10-desktop2.2 通信功能分析实现聊天程序,并要考虑服务器能够同时处理多个客户的连接请求,实现客户端通过服务器的转发通信。则通信过程分析如下:服务器端: 1)建立socket绑定监听端口; 2)等待客户端的连接;3)当客户与服务器建立连接后,服务器记录客户所有信息,如ID号;4)当客户消息到达服务器后,服务器分析客户信息:a.若为转发消息,根据消息格式提供的转发ID号,服务器立即查找转发列表,转发消息,若查找后发现需要转发的客户ID不存在则返回错误信息给原客户,提示不存在要发送的客户端ID号;b.若为询问消息,服务器返回当前登录

3、到服务器的所有客户的ID号;c.若为退出消息,服务器清楚当前客户的所有信息,更新客户列表;5)以上2-4步都是随时进行的:a.任何新进客户端都能随时连接服务器;b.任何以连接客户端都能发送消息,并且服务器能同时处理多个同时到来的消息,实现并发的处理客户端消息。 6)当服务器停止工作时,关闭监听套接字。客户端 : 1)建立连接到服务器的socket; 2)发送登录信息,信息中需要包含自身的ID号,使服务器能识别本机;3)使用信号机制,随时能接收服务器传来的消息,不阻塞,及时的显示到来信息,并记录到来信息,以方便用户查看聊天记录; 4)能随时向服务器发送消息,有三种消息: a.询问消息,询问服务器

4、当前已连接到服务器的客户列表; b.转发消息,告知服务器需要转发的ID号和信息,通过服务器进行聊天; c.退出消息,告知服务器本客户端要退出聊天;5)要获取当前以登录服务器的客户列表,则会发送询问消息,得到返回结果后更新本地的用户登录列表;6)当想退出时,向服务器端发送退出消息后,关闭套接字,关闭程序。2.3 设计协议 通过以上服务器与客户端功能的分析,要完成以上功能,需要设计一个通信协议。1)通信消息协议格式协议格式中需要包含的信息有:用户的ID号、接收者的ID号、退出标记、查询标记、转发标记、信息内容。所以构造如下:a.协议使用基于文本的格式:chat#b.相应使用到的结构体:struct

5、 ChatMsg char ID20; /自己的ID号 char toID20; /需要发送的ID号 bool isQuit; /发送的是退出消息时为true bool isInquiry; /发送的是询问消息时为true char msg128; /需要发送的信息内容;c.字符串“chat”,是魔术字符串,因为不能确定消息在传送过程中是否会出现问题,所以使用一个字符串测试消息的正确性;d.字符串“”,表明发送消息的客户端自己的ID号;e.字符串“”,当要转发消息时,此字符串表明要转发的目的客户端ID号;f.字符串“”,当被标识为q时,表示退出,标识为i时,表示询问,标识为u时,表示默认转发,

6、q与i可以同时放在一起,因为如果是询问消息,则不可能是退出消息,反之如果是退出消息就不可能是询问消息;g.字符串“”,表示要发送的信息内容;h.字符串协议中,使用#字符表示分隔符,用以分隔各个字段。2)通信消息协议实现 通过此协议格式,可以实现三种消息的通信(如客户ID:wang,消息发送到ID:zhao): a.询问消息:chat#wang#server#i# # b.转发消息:chat#wang#zhao#u#hello.# c.退出消息:chat#wang#server#q# # 消息协议的实现使用Coder.c实现消息的编码,此文件中有如下两个函数: /*实现消息的编码,输入消息Cha

7、tMsg结构体,返回消息字符串与长度*/ size_t Encode(struct ChatMsg *cmsg, uint8_t *outBuf, size_t bufSize); /*实现消息的解码,输入消息字符串,返回消息ChatMsg结构体与消息长度*/int Decode(uint8_t *inBuf, size_t mSize,struct ChatMsg *cmsg);2.4 程序所使用技术 根据对通信功能的分析,需要用到相应的技术解决通信过程中需要完成的功能,经过分析,发现需要完成的主要功能有四项:1)基本消息传输;2)不阻塞接收消息;3)服务器并发处理多客户消息;4)程序界面易

8、操作性。本实验对应不同的功能,提供不同的技术解决方案,各项功能实现技术描述如下。2.4.1 基本消息传输1)采用UDP协议传送消息,采用此技术传送消息主要考虑到其简单性,容易在程序中实现,并且不需要考虑面向连接所要解决的问题,如何建立与何时断开连接都是在用TCP时需要考虑的问题,还有就是消息的成帧,在TCP中需要考虑成帧的问题,在TCP中有两种解决办法,一直是以定界符的方式,另一种是以固定长度的方法,而在UDP中并不需要考虑这个问题,因为使用UDP传送时,消息的边界已经是确定的了,而无需再去指定,所以使用UDP只需要考虑如何编码协议即可,但采用UDP也有很大的问题,那就是UDP本身固有的缺点,

9、消息传送的不安全性,无重传的机制,无法知道消息是否到达。 2)UDP技术的实现: a. 服务器端建立UDP socket并绑定监听socket:(核心代码) server_socket= socket(servAddr-ai_family, servAddr-ai_socktype, servAddr-ai_protocol); bind(server_socket, servAddr-ai_addr, servAddr-ai_addrlen); b. 客户端建立UDP socket并通过指定端口连接到服务器:(核心代码) my_socket = socket(servAddr-ai_fami

10、ly, servAddr-ai_socktype, servAddr-ai_protocol);2.4.2 不阻塞接收消息1)采用信号量机制,实现不阻塞接收消息,当有I/O信号到来的时候才调用相应的函数处理到来的消息,这样可以让出CPU去执行其他的代码,提高了程序的执行效率,这样作的好处显而易见。在此程序中使用了GTK+2.0的图形界面编程技术,所以在实现上与书本所介绍的方法并不一致。2)服务器端与客户端都实现了采用信号量机制的消息接收方式:a. 服务器端采用信号量机制接收信息:(核心代码)/*监听以创建的socket端口是否有输入信号准备好;*若信号已准备好则调用线程处理函数ThreadHa

11、ndle()处理到来消息*/gdk_input_add(server_socket,GDK_INPUT_READ,ThreadHandle,NULL );b. 客户端采用信号量机制接收信息:(核心代码)/*监听以创建的socket端口是否有输入信号准备好;*若信号已准备好则调用函数SIGReceive()处理到来消息*/gdk_input_add(my_socket,GDK_INPUT_READ,SIGReceive,NULL );2.4.3 服务器并发处理多客户消息1)服务器需要并发的处理多个客户同时发送信息的要求,考虑使用多线程技术,实现并发的处理信息,因为没有使用TCP协议来实现此程序,

12、所以不能使用accpet函数接收客户端的连接,并单独的为每位客户端创建一个线程来处理消息的转发。但在UDP的实现中一样需要用到线程技术来解决并发的处理客户消息,因为不同客户的消息可能会同时到达,若不采用多线程技术,则会出现如下这样的情况:先前到达的消息还没处理完又有新的消息到达,而新到达的消息则会等待,若还有其它消息的到达,也都会等待,当客户端的数量达到一定程度时,如不使用线程技术处理到来的消息,则会使整个通信过程产生很大的时延,有可能还会使服务器瘫痪(如一个消息在处理过程中出错,程序暂停执行)。所以考虑使用多线程技术实现客户端消息的并发处理。2)服务器端多线程技术的实现,因为使用了GTK+2

13、.0图形界面编程,所以在实现多线程上与课本上的实现不太相同:(核心代码)/*首先使用信号量技术,监听以创建的socket端口是否有输入信号准备好;*若信号已准备好则调用线程处理函数“ThreadHandle()“处理到来消息*/gdk_input_add(server_socket,GDK_INPUT_READ,ThreadHandle,NULL );/*以下为线程处理函数,当有I/O信号到来时会调用此函数创建一个线程,*实现消息的并发处理。此线程完成对每个客户消息的处理,调HandleClient()函数 */void ThreadHandle() g_thread_create(GThre

14、adFunc)HandleClient, NULL, FALSE, NULL);2.4.4 程序界面易操作性考虑到此实验实现起来的复杂性,并不是太困难,所以考虑使用图形界面的方式呈现此聊天程序,使程序有更好的用户体验,而不是面对一个由一堆字符组成的终端界面。同时因为个人喜好问题,所以选择了Linux下的图形界面设计,采用GTK+进行图形界面设计,此处就不对GTK的编程细节进行描述,在实验运行结果图中会展示使用GTK+所创建的图形界面。3、实验运行结果图3.1 实验准备1)服务器监听端口号:3693;服务器地址:127.0.0.1、192.168.10.3、 (在/etc/hosts中设置,因为

15、程序使用了getaddrinfo()函数可以识别此地址)2)客户端需要获得:服务器的端口号与IP地址;客户端准备自己的ID号唯一识别一台主机,此实验中开始三个客户端分别为:wang1客户、wang2客户、wang3客户。3)实验所用程序名:服务器端为ServerWindow,客户端为ClientWindow3.2 实验拓扑图3.3 通信过程截图1)点击“Start“按钮,启动服务器,监听3693端口图1 服务器端界面2)客户wang1,启动客户端程序,输入服务器IP地址127.0.0.1,端口号3693,客户ID为wang1,点击”Connect”按钮连接服务器,连接成功后会弹出对话框,通知连

16、接成功。图2 客户端界面,wang1客户3)客户wang2,启动客户端程序,输入服务器地址,端口号3693,客户ID为wang2,点击”Connect”按钮连接服务器,连接成功后会弹出对话框,通知连接成功。(如图3)4)客户wang3,启动客户端程序,输入服务器地址192.168.10.3,端口号3693,客户ID为wang3,点击”Connect”按钮连接服务器,连接成功后会弹出对话框,通知连接成功。(如图4) 图3 wang2客户 图4 wang3客户5)当三个客户端都连接上服务器后,服务器列表增加了三个客户信息,同时客户点击刷新按钮“Refresh online users”时,会获取服

17、务器当前以登录客户端的客户ID6)wang2与wang3向wang1发送消息如图7图8图7 wang2向wang1发送消息 图8 wang3向wang1发送消息7)wang1接收到wang2与wang3发来的消息,消息会直接显示,查看聊天记录使用按钮“front”与“next”,如图9图10图9 按front按钮查看wang2的消息 图10 按next按钮查看wang3的消息8)wang1客户端向一个不存在的客户端(如wang4)发送信息时,服务器会返回消息提示不存在此客户,如图11图12图11 向不存在客户端(wang4)发信息 图12 服务器返回信息,提示wang4不在线9)wang1点击

18、按钮“Close”退出聊天室,服务器刷新客户列表去除wang1用户,同时使用wang2向wang1发送信息,提示wang1不在线,如图13图14图13 服务器列表中已没有wang1用户 图14向wang1发送信息提示wang1不在线10)测试结果显示,服务器和客户端能完成聊天任务,实验成功。4、实验程序文件与源代码4.1 实验所使用的文件 1)服务器端使用文件:ChatComponent.h Coder.c MessageDialog.c ServerWindow.c2)客户端使用文件:ChatComponent.h Coder.c MessageDialog.c SendAndReceive

19、.c ClientWindow.c 3)各文件说明:a. ChatComponent.h 此头文件中包含有:对应本程序协议的结构体,与功能函数的声明,客户端与服务器端的这个文件并不完全相同; b. Coder.c 编码文件,使用本程序设计的协议进行编码与解码; c. MessageDialog.c 消息提示组件,用于弹出提示对话框,因使用频繁所以单独写成文件; d. ServerWindow.c 服务器端文件,存放服务器端程序原代码; e. SendAndReceive.c 客户端使用的文件,使用此文件进行信息的发送与接收; f. ClientWindow.c 客户端文件,存放客户端程序源代码

20、; 4)编译所使用的命令:服务器端编译命令:gcc pkg-config gtk+-2.0 -cflags -libs gthread-2.0 -std=gnu99 -o ServerWindow ServerWindow.c ChatComponent.h Coder.c MessageDialog.c服务器端程序名:ServerWindow客户端编译命令:gcc pkg-config -cflags -libs gtk+-2.0 -std=gnu99 -o ClientWindow ClientWindow.c ChatComponent.h Coder.c SendAndReceive.

21、c MessageDialog.c 客户端程序名:ClientWindow4.2 实验文件源代码1)ChatComponent.h 客户端#ifndef CHATCOMPONENT_H_#define CHATCOMPONENT_H_#include #include #include #include #include #include #include /最大发送字符#define MAXBUF 256/最大记录信息条数#define MAXMSGNUM 30/消息协议所对应的结构体struct ChatMsg char ID20;/id from self char toID20;/id

22、 from another bool isQuit;/tell the server quit bool isInquiry;/inquiry server online users char msg128; /chat message;/聊天历史记录struct RecvMsg char fromID20; char msg128;/记录聊天历史记录的队列,使用数字队列struct QueueIndex int front; int rear;/对话框消息int SystemInfo(char *from,char *msg);/消息的编码与解码函数size_t Encode(struct

23、ChatMsg *cmsg, uint8_t *outBuf, size_t bufSize);int Decode(uint8_t *inBuf, size_t mSize,struct ChatMsg *cmsg);/方便客户端对消息的发送与接收int SendMsg(struct addrinfo *servAddr,int socket,struct ChatMsg *cmsg);int ReceiveMsg(struct addrinfo *servAddr,int socket,struct ChatMsg *cmsg);#endif / CHATCOMPONENT_H_2)Cha

24、tComponent.h 服务器端#ifndef CHATCOMPONENT_H_#define CHATCOMPONENT_H_#include #include #include #include #include #include #include #include /最大发送字符#define MAXBUF 256/最大连接客户数#define MAXCONNECT 30/消息协议所对应的结构体struct ChatMsg char ID20;/id from self char toID20;/id from another bool isQuit;/tell the server

25、quit bool isInquiry;/inquiry server online users char msg128; /chat message;/记录连接客户的信息struct RecordClient char clntID20; struct sockaddr_storage clntAddr; socklen_t clntAddrLen;/对话框消息int SystemInfo(char *from,char *msg);/消息的编码与解码函数size_t Encode(struct ChatMsg *cmsg, uint8_t *outBuf, size_t bufSize);

26、int Decode(uint8_t *inBuf, size_t mSize,struct ChatMsg *cmsg);#endif / CHATCOMPONENT_H_3)Coder.c#include #include #include #include #include #include ChatComponent.h/* 消息采用文本编码方式. * 文本编码格式:chat#*/static const char *MAGIC=chat;static const char *QUIT=q;static const char *INQUIRY=i;static const char *

27、DELIMSTR=#;/*编码函数,输入消息结构体变量,返回字符串*/size_t Encode(struct ChatMsg *cmsg, uint8_t *outBuf, size_t bufSize) uint8_t *bufPtr = outBuf; long size = (size_t) bufSize; int rv=snprintf(char *)bufPtr,size,%s#%s#%s#%s#%s#, MAGIC,cmsg-ID,cmsg-toID, (cmsg-isQuit?QUIT:(cmsg-isInquiry?INQUIRY:u),cmsg-msg); bufPtr

28、+= rv; return (size_t) (bufPtr - outBuf);/*解码函数,输入字符串,返回消息结构体变量*/int Decode(uint8_t *inBuf, size_t mSize,struct ChatMsg *cmsg) char *token; token = strtok(char *) inBuf, DELIMSTR); / Check for magic if (token = NULL | strcmp(token, MAGIC) != 0)return -1; / Get ID token = strtok(NULL, DELIMSTR); if (

29、token = NULL) return -1; strcpy(cmsg-ID,token); strcat(cmsg-ID,0); /Get toID token = strtok(NULL, DELIMSTR); if (token = NULL) return -1; strcpy(cmsg-toID,token); strcat(cmsg-toID,0); /Get isQuit or isInquiry token = strtok(NULL, DELIMSTR); if (token = NULL) return -1; if (strcmp(token, QUIT) = 0) cmsg-isQuit=true; cmsg-isInquiry=false; else if(strcmp(token, INQUIRY) = 0) cmsg-isQuit=false; cmsg-isInquiry=true; else cmsg-isQuit=false; cms

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1