信息处理课程设计实践报告-聊天软件设计.doc_第1页
信息处理课程设计实践报告-聊天软件设计.doc_第2页
信息处理课程设计实践报告-聊天软件设计.doc_第3页
信息处理课程设计实践报告-聊天软件设计.doc_第4页
信息处理课程设计实践报告-聊天软件设计.doc_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

信息处理课程设计实践报告题 目: 聊 天 软 件 班 级: 信科04-4班 学 号: 姓 名: 指导教师: 中国矿业大学计算机学院2007-1-11摘 要本文介绍了一个基于client/server模式的聊天软件的设计与实现。运用visual c+ 6.0开发,利用mfc对话框开发软件界面。 本软件分两个模块:服务器端和客户端。采用winsock编程技术,实现了点对点的通信。服务器和客户端工程在网络方面都单独设计了socket相关类继承与windows csocket类,封装性好。很好的体现了面向对象的设计思想和开发方法。软件实现上采用了多线程技术。不但实现了普通聊天软件的网络聊天功能,还增加了网络文件传输和抓取对方屏幕截图的功能。关键词 qq聊天 聊天软件 csocket 网络编程 课程设计目 录3第1章 课题概述11.1 课题目的与意义11.2 课程设计及报告的说明2第2章 网络编程相关的理论与技术32.1 计算机网络模型32.1.1 osi的7层模型32.1.2 tcp/ip模型52.2 网络应用程序62.3winsock 编程82.4多线程12第3章 聊天软件的设计与实现183.1 服务器端实现183.1.1 服务器端资源准备183.1.2 服务器端程序实现193.2 客户端实现223.2.1 客户端资源准备223.2.2 客户端程序实现273.3聊天软件的其他技术29结 束 语30参考文献32第1章 课题概述1.1 课题目的与意义本课程设计是网络通信课程设计,课题可以有1、设计组织局域网2、网络通信程序设计(基于各类网络协议,例如tcp、udp等等)。我们选择实现一个网络通信软件。利用网络协议和windows编程技术做一个简易qq。 通过本课程设计的实现,我们能进一步掌握常用的网络协议及其在程序中的运用。同时,也更进一步学习和熟练windows编程技术,加强自己的动手能力。并且一个这样的聊天软件在设计上是可以在教育网用户给同学们之间免上公网聊天的,而且还可以快速传输一些文件,对于距离比较远的两个人是相当实用的,另外,增加的抓取对方屏幕截图功能可以在远程帮助对方解决一些难以用语言描述的问题,对于电脑新用户远程请教或求助极其方便。当然,要使其更实用还有待进一步完善,不过我们的这个课题在设计上是具备以上意义的。 1.2 课程设计及报告的说明本次课程设计由我和曾亮组成一个小组共同完成。本次课程设计设计报告组织结构为:1、课题概述;2、网络编程相关的理论与技术;3、软件的设计与实现;4、结束语; 5、参考文献;第2章 网络编程相关的理论与技术2.1 计算机网络模型网络有多种多样的分层模型,这里介绍osi的7层模型和tcp/ip模型。2.1.1 osi的7层模型osi模型是由iso(国际标准化组织)的建议发展起来的,称作“开放式系统互连参考模型” 。osi模型一共分为7层,如下图,分层的原则主要是: (1) 当需要有一个不同等级的抽象时,就应当有一个相应的层次。(2) 每一层的功能是明确的。(3) 层与层的边界选择应使通过这些边界的信息量尽量少。(4) 层数不能太多或者太少: 层数太少会使每一层的协议太复杂;层数太多,又会是描述合作和各层功能的系统工作任务时,遇到较多的困难。以下简单说明各层及其功能:(1) 物理层向上层提供物理连接,透明传送比特流。(2) 数据链路层负责在相邻的两个站点间无差错的传送以帧为单位的数据。他要负责差错控制,流量控制。(3) 网络层主要功能是从源端到目的端为传送的数据选择一条合适的路由,还要解决拥塞控制问题。(4) 传输层负责为会话层建立一条网络连接,解决流量控制问题。(5) 会话层主要是负责对数据传输进行管理。(6) 表示层主要解决用户信息的语法表示问题。(7) 应用层这一层包括了大量人们需要的协议。应用层确定用户通信的性质以满足用户的需要。2.1.2 tcp/ip模型在目前的计算机网络上被广泛采用的是tcp/ip参考模型,他是一个与osi模型相比更简单高效的模型,tcp/ip模型是一个四层的模型系统,如下图:tcp/ip最初提出的是协议,模型其实是对已有协议的描述,这里简要介绍tcp/ip四层模型及作用:(1) 网络接口层这一层指出主机必须使用某种协议与网络连接。(2) 互联网层这一层定义了分组格式和协议,及ip协议。(3) 传输层使源端和目的端主机上的对等实体可以进行会话。这里定义了两个端到端协议:tcp和udp。(4) 应用层它包含所有的高层协议,例如telnet协议,ftp协议,smtp协议,http协议等。下图还给出了这两种模型的层次对应关系及比较:2.2 网络应用程序网络应用程序包括两个部分:一部分是服务器端的应用程序;另一部分是客户端的应用程序。但在网络应用程序中,不管是服务器端还是客户端,发送数据是主动的,而接收数据总是被动的。服务器为客户端请求建立一个socket,以处理客户端的数据通信请求。服务器端为了接收客户端的数据,在为客户端建立的socket上建立消息响应函数onreceive,用来接受数据。客户端为了接受服务器端的数据,则在连接的socket上,建立一个消息响应函数onreceive,用来接收数据。一般网络应用程序实现包括以下几个步骤:(1) 建立socket对象:可以使用casyncsocket或csocket建立对象,一般使用csocket来建立socket对象。(2) 建立连接:客户端必须要连接到服务器端,同时指定服务器地址和端口号。(3) 发送和接收数据。(4) 监听socket:对于服务器端,建立连接后,必须创建监听线程,以便随时能够监测到是否有客户端的连接请求。(5) 为客户端连接请求建立socket队列:服务器端要同时处理多个客户端的请求,与多个客户端实现并行通信,因此监测到有客户端的连接请求,须为每个客户端均建立一个socket,以便通信时不至于发生混乱。2.3 winsock 编程通过winsock可实现点对点或广播通信程序,实际这两者之间的区别不大,编程时其程序流程所用代码几乎相同,不同的地方在于目标地址选择的不同。本课程中所举实例为点对点的形式,并以客户/服务器形式来构建通过winsock进行通信的点对点通信,并对通信过程的两点分别命名为server和client。为更清楚的说明出winsock的结构原理,下面以电信局的普通电话服务为比较对象进行说明:1、电信局提供电话服务类似版主们这的server,普通电话用户类似版主们这的client。2、首先电信局必须建立一个电话总机。这就如果版主们必须在server端建立一个socket(套接字),这一步通过调用socket()函数实现。3、电信局必须给电话总机分配一个号码,以便使用户要拨找该号码得到电话服务,同时接入该电信局的用户必须知道该总机的号码。同样,版主也在server端也要为这一套接字指定一port(端口),并且要连接该server的client必须知道该端口。这一步通过调用bind()函数实现。4、接下来电信局必须使总机开通并使总机能够高效地监听用户拨号,如果电信局所提供服务的用户数太多,你会发现拨打电信局总机老是忙音,通常电信局内部会使该总机对应的电话号码连到好几个负责交换的处理中心,在一个处理中心忙于处理当前的某个用户时,新到用户可自动转到一下处理中心得到服务。同样版主们的server端也要使自己的套接口设置成监听状态,这是通用listen()函数实现的,listen()的第二个参数是等待队列数,就如同你可以指定电信局的建立几个负责交换的处理中心。5、用户知道了电信局的总机号后就可以进行拨打请求得到服务。在winsock的世界里做为client端是要先用socket()函数建立一个套接字,然后调connect()函数进行连接。当然和电话一样,如果等待队列数满了、与server的线路不通或是server没有提供此项服务时,连接就不会成功。5、电信局的总机接受了这用户拨打的电话后负责接通用户的线路,而总机本身则再回到等待的状态。server也是一样,调用accept()函数进入监听处理过程,server端的代码即在中处暂停,一旦server端接到申请后系统会建立一个新的套接字来对此连接做服务,而原先的套接字则再回到监听等待的状态。6、当你电话挂完了,你就可以挂上电话,彼此间也就离线了。client和server间的套接字的关闭也是如此;这个关闭离线的动作,可由client端或server端先关闭。有些电话查询系统不也是如此吗?关闭套接字的函数为closesocket()从以上情况可以看出在服务器端建立一个套接字,并进入实际的监听步骤的过程如下:socket()-bind()-listen()-accept()那么在accept()完了后,版主们说在server端将生成一个新的套接字,然后server将继续进入accept()状态,版主们该如何用这个新的套接字来进行与client端的通信呢,这就用到了recv()函数,而client端则是通过send()函数来向服务器发信息的。在客户端也是采取类似的过程,其调用winsock的过程如下:socket()-connect()-send()首先建立一个socket,然后用connect()函数将其与server端的socket连接,连接成功后调用send()发送信息。2.4 多线程线程概述进程和线程都是操作系统的概念。进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭。线程是进程内部的一个执行单元。系统创建好进程后,实际上就启动执行了该进程的主执行线程,主执行线程以函数地址形式,比如说main或winmain函数,将程序的启动点提供给windows系统。主执行线程终止了,进程也就随之终止。每一个进程至少有一个主执行线程,它无需由用户去主动创建,是由系统自动创建的。用户根据需要在应用程序中创建其它线程,多个线程并发地运行于同一个进程中。一个进程中的所有线程都在该进程的虚拟地址空间中,共同使用这些虚拟地址空间、全局变量和系统资源,所以线程间的通讯非常方便,多线程技术的应用也较为广泛。多线程可以实现并行处理,避免了某项任务长时间占用cpu时间。要说明的一点是,目前大多数的计算机都是单处理器(cpu)的,为了运行所有这些线程,操作系统为每个独立线程安排一些cpu时间,操作系统以轮换方式向线程提供时间片,这就给人一种假象,好象这些线程都在同时运行。由此可见,如果两个非常活跃的线程为了抢夺对cpu的控制权,在线程切换时会消耗很多的cpu资源,反而会降低系统的性能。这一点在多线程编程时应该注意。win32 sdk函数支持进行多线程的程序设计,并提供了操作系统原理中的各种同步、互斥和临界区等操作。visual c+ 6.0中,使用mfc类库也实现了多线程的程序设计,使得多线程编程更加方便。win32 api对多线程编程的支持win32 提供了一系列的api函数来完成线程的创建、挂起、恢复、终结以及通信等工作。下面将选取其中的一些重要函数进行说明。 1、handlecreatethread(lpsecurity_attributes lpthreadattributes, dword dwstacksize, lpthread_start_routine lpstartaddress, lpvoid lpparameter, dword dwcreationflags, lpdword lpthreadid);该函数在其调用进程的进程空间里创建一个新的线程,并返回已建线程的句柄,其中各参数说明如下:lpthreadattributes:指向一个 security_attributes 结构的指针,该结构决定了线程的安全属性,一般置为 null; dwstacksize:指定了线程的堆栈深度,一般都设置为0; lpstartaddress:表示新线程开始执行时代码所在函数的地址,即线程的起始地址。一般情况为(lpthread_start_routine)threadfunc,threadfunc 是线程函数名; lpparameter:指定了线程执行时传送给线程的32位参数,即线程函数的参数; dwcreationflags:控制线程创建的附加标志,可以取两种值。如果该参数为0,线程在被创建后就会立即开始执行;如果该参数为create_suspended,则系统产生线程后,该线程处于挂起状态,并不马上执行,直至函数resumethread被调用; lpthreadid:该参数返回所创建线程的id; 如果创建成功则返回线程的句柄,否则返回null。 2、dword suspendthread(handle hthread);该函数用于挂起指定的线程,如果函数执行成功,则线程的执行被终止。3、dword resumethread(handle hthread);该函数用于结束线程的挂起状态,执行线程。 4、void exitthread(dword dwexitcode);该函数用于线程终结自身的执行,主要在线程的执行函数中被调用。其中参数dwexitcode用来设置线程的退出码。 5、bool terminatethread(handle hthread,dword dwexitcode);一般情况下,线程运行结束之后,线程函数正常返回,但是应用程序可以调用terminatethread强行终止某一线程的执行。各参数含义如下:hthread:将被终结的线程的句柄; dwexitcode:用于指定线程的退出码。 使用terminatethread()终止某个线程的执行是不安全的,可能会引起系统不稳定;虽然该函数立即终止线程的执行,但并不释放线程所占用的资源。因此,一般不建议使用该函数。 6、bool postthreadmessage(dword idthread, uint msg, wparam wparam, lparam lparam);该函数将一条消息放入到指定线程的消息队列中,并且不等到消息被该线程处理时便返回。idthread:将接收消息的线程的id; msg:指定用来发送的消息; wparam:同消息有关的字参数; lparam:同消息有关的长参数; 调用该函数时,如果即将接收消息的线程没有创建消息循环,则该函数执行失败。第3章 聊天软件的设计与实现3.1 服务器端实现聊天软件服务器端完成网络通信中的服务器功能,除了建立socket对象,监听socket连接以外,还为客户端建立了socket队列,即允许多个客户端连接到同一服务器,并且服务器端还支持对连上服务器的客户单个或者群发消息的功能,及可以实现网上答疑室功能。3.1.1 服务器端资源准备服务器端只是一个简单的对话框界面,没有做过多的修饰,但也简单大方。在服务器端可以显示客户端的连接状态,可以自己设定要监听的端口,还可以对任意一个客户端发送消息,也可以广播式的群发消息。对话框(dialog)包括管理界面对话框和关于(about)信息对话框采用一种简洁大方的设计,便于操作。服务器端的资源准备比较简单,以下是运行时截取的画面,具体介绍参见3.3节。3.1.2 服务器端程序实现1在初始化阶段调用wsastartup()此函数在应用程序中初始化windows sockets dll ,只有此函数调用成功后,应用程序才可以再调用其他windows sockets dll中的api函数。在程式中调用该函数的形式如下:wsastartup(word)(18|1),(lpwsadata)&wsadata),其中(18|1)表示我们用的是winsocket1.1版本,wsaata用来存储系统传回的关于winsocket的资料。2、建立socket初始化winsock的动态连接库后,需要在服务器端建立一个监听的socket,为此可以调用socket()函数用来建立这个监听的socket,并定义此socket所使用的通信协议。此函数调用成功返回socket对象,失败则返回invalid_socket(调用wsagetlasterror()可得知原因,所有winsocket 的api函数都可以使用这个函数来获取失败的原因)。如果要建立的是遵从tcp/ip协议的socket,第二个参数type应为sock_stream,如为udp(数据报)的socket,应为sock_dgram。3、绑定端口接下来要为服务器端定义的这个监听的socket指定一个地址及端口(port),这样客户端才知道待会要连接哪一个地址的哪个端口,为此我们要调用bind()函数,该函数调用成功返回0,否则返回socket_error。 如果使用者不在意地址或端口的值,那么可以设定地址为inaddr_any,及port为0,windows sockets 会自动将其设定适当之地址及port (1024 到 5000之间的值)。此后可以调用getsockname()函数来获知其被设定的值。4、监听当服务器端的socket对象绑定完成之后,服务器端必须建立一个监听的队列来接收客户端的连接请求。listen()函数使服务器端的socket 进入监听状态,并设定可以建立的最大连接数(目前最大值限制为 5, 最小值为1)。该函数调用成功返回0,否则返回socket_error。服务器端的socket调用完listen()后,如果此时客户端调用connect()函数提出连接申请的话,server 端必须再调用accept() 函数,这样服务器端和客户端才算正式完成通信程序的连接动作。为了知道什么时候客户端提出连接要求,从而服务器端的socket在恰当的时候调用accept()函数完成连接的建立,我们就要使用wsaasyncselect()函数,让系统主动来通知我们有客户端提出连接请求了。该函数调用成功返回0,否则返回socket_error。5、服务器端接受客户端的连接请求当client提出连接请求时,server 端hwnd视窗会收到winsock stack送来我们自定义的一个消息,这时,我们可以分析lparam,然后调用相关的函数来处理此事件。为了使服务器端接受客户端的连接请求,就要使用accept() 函数,该函数新建一socket与客户端的socket相通,原先监听之socket继续进入监听状态,等待他人的连接要求。该函数调用成功返回一个新产生的socket对象,否则返回invalid_socket。6、结束 socket 连接结束服务器和客户端的通信连接是很简单的,这一过程可以由服务器或客户机的任一端启动,只要调用closesocket()就可以了,而要关闭server端监听状态的socket,同样也是利用此函数。另外,与程序启动时调用wsastartup()憨数相对应,程式结束前,需要调用 wsacleanup() 来通知winsock dll释放socket所占用的资源。这两个函数都是调用成功返回0,否则返回socket_error。3.2 客户端实现3.2.1 客户端资源准备为了让软件更容易使用,该聊天软件的界面和操作都腾讯qq为基础,又加上了自己的设计。这里我们用图标提取工具从腾讯qq中提取了一些头像图片,目的是为了让我们的软件看起来更亲切!而且软件中的头像图标有大小两种不同的显示方式。在工作空间中选择resource 进入资源编辑,插入位图(bitmap),这里先准备两张不同大小的位图作为头像,并设置id。在制作不同的光标(cursor),在用户鼠标在不同位置时显示不同的光标,并设置id。然后插入图标(icon)。完成这些,就该制作对话框了(dialog)。对话框由自己设计,包括注册对话框,登陆对话框,用户管理界面对话框,消息通知对话框,聊天对话框和关于(about)信息对话框。运行时效果如图: 3.2.2 客户端程序实现1、建立客户端的socket客户端应用程序首先也是调用wsastartup()函数来与winsock的动态连接库建立关系,然后同样调用socket()来建立一个tcp或udp socket(相同协定的sockets才能相通,tcp对tcp,udp对udp)。与服务器端的socket不同的是,客户端的socket可以调用bind()函数,由自己来指定ip地址及port号码;但是也可以不调用 bind(),而由 winsock来自动设定ip地址及port号码。2、提出连接申请客户端的socket使用connect()函数来提出与服务器端的socket建立连接的申请,函数调用成功返回0,否则返回socket_error。数据的传送虽然基于tcp/ip连接协议(流套接字)的服务是设计客户机/服务器应用程序时的主流标准,但有些服务也是可以通过无连接协议(数据报套接字)提供的。先介绍一下tcp socket 与udp socket在传送数据时的特性:stream (tcp) socket提供双向、可靠、有次序、不重复的资料传送。datagram(udp) socket虽然提供双向的通信,但没有可靠、有次序、不重复的保证,所以udp传送数据可能会收到无次序、重复的资料,甚至资料在传输过程中出现遗漏。由于udp socket 在传送资料时,并不保证资料能完整地送达对方,所以绝大多数应用程序都是采用tcp处理socket,以保证资料的正确性。一般情况下tcp socket 的数据发送和接收是调用send() 及recv() 这两个函数来达成,而 udp socket则是用sendto() 及recvfrom() 这两个函数,这两个函数调用成功返回发送或接收的资料的长度,否则返回socket_error。对于datagram socket而言,若是 datagram 的大小超过限制,则将不会送出任何资料,并会传回错误值。对stream socket 言,blocking 模式下,若是传送系统内的储存空间不够存放这些要传送的资料,send()将会被block住,直到资料送完为止;如果该socket被设定为 non-blocking 模式,那么将视目前的output buffer空间有多少,就送出多少资料,并不会被 block 住。flags 的值可设为 0 或 msg_dontroute及 msg_

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论