我的毕业设计论文,毕业设计论文袋将包括两大部分,一份就是论文正文本身,另一份是毕业设计相关资料,其中包括:开题报告书,任务书,文献综述报告,过程记录,老师指导记录,外文译文(1000字)。
局域网通信工具的设计与实现
作者姓名: 专业班级:2003050305 指导教师:
摘 要
随着计算机网络技术的发展,各种各样基于网络的应用也随之诞生,比如基于互联网的信息发布,通信,数据共享等等。局域网的发展也同样迅速。很多*机构,企业,学校,都是先以一个统一的局域网联结在一起,再分别接入INTERNET.因此基于局域网的即时通信工具,就这样应运而生了。所以本文提出了一个更加合理的设计,并在WINDOWS平台上加以了实现.在本实现内将客户端和服务端综合在一个程序之内,用多线程实现不同的并行任务。并进行了人性化的界面设计,使用起来更加简单方便,并且功能十分合理,又易于扩展以及个性化定制。
关键词:局域网;即时通信;客户端;服务端;多线程
The Design and Implementation of LAN IM
Abstract:Along with the high-speed development of the computer network technology, various of applications based on network was born, like information releasing, data sharing ... The development of the LAN is the same fast. Some governments, enterprises and schools constitute a LAN first ,then join into INTERNET. So the instant messenger in LAN was borned. So I make a new design, and implement it on WINDOWS platform. In my implementation the client and the server were integrated in one program with multi thread mechanism. And had a good GUI,it was very easy to use it. And the function is very realizable. At last, it is also easy for expanding.
Key words: LAN, instant messaging, client, server, multi thread
目 录
1.4.2 WINDOWS SOCKETS网络编程接口概述... 3
3.2 TCP/IP 协议及WINDOWS SOCKETS网络编程接口... 9
3.2.2 WINDOWS SOCKETS网络编程接口概述... 12
第1章 引 言
1.1课题背景及意义
近年来,随着全球信息化进程的不断发展,网络也在飞速发展。出于高效、快速地处理各种事务的目的,越来越多的企业在其内部使用局域网来进行工作。在内部局域网的帮助下,企业得以简化信息流程,提高信息交换的速度,从而提高工作效率。然而,随着企业规模的扩大,业务量的增加,在局域网上运行的应用越来越多,如知识库、网络会议、数据库应用和数据的同步与备份等,这些应用对局域网的信息吞吐、处理能力的要求也越来越高。这些在企业内部原有局域网设计之初未曾考虑到的新情况的出现使得局域网不堪重负,容易发生信息阻塞,此时,局域网不但不能提高生产效率,反而成为企业发展的瓶颈。
为了解决上述矛盾,人们提出了许多方法。提升网络带宽及增加服务器的吞吐能力是解决此矛盾的一种方法。然而,从企业运行的成本方面考虑,无论是单纯地提升网络带宽或增加服务器的吞吐能力都不能从根本上解决局域网资源紧张的问题,对旧有局域网的大规模硬件改*而会增加企业的负担。
我在本文中将讨论一种基于Socket的局域网通信工具的设计与实现方法。基于Socket的局域网通信软件可以为企业原有的局域网提供一种良好,安全,快速的通信机制。它的实现无需对企业原有的局域网硬件进行任何改动,具有实现成本低廉的优点,它的使用能有效地降低局域网通信负荷,提高局域网的使用效率,可以很好地解决企业内部局域网的各种通信需求。
基于Socket的局域网聊天工具是此类局域网通信软件的具体实例之一,它很好地诠释了Socket通信的原理,并且在企业内部通信、教学、讨论等应用中都具有一定的实用价值。它具有信息收发速度快,保密性好,占用网络带宽资源低,占用服务器吞吐能力低,易于编程实现等优点。
基于Socket的局域网通信软件应用范围广阔,不但可以处理传统的通信需求,而且也能扩展以适应新型的网络应用,如网络教育,数据影音传输等,拥有广泛的应用前景。
1.2 课题现状
基于局域网的即时通信工具,实际上是互联网即时通信工具的一个小规模版本,广域网上的即时通信工具,如今一般采用UDP或者 TCP协议体系来实现 ,开发技术已经比较成熟,比如较早的ICQ,MSN Messanger,Yahoo 通这些国外开发的产品,还有国产的有名的QQ,新浪UC,LAVA-LAVA等,这些工具统统都实现了广域网上的即时通信,尽管都是即时通信,实现了即时聊天,以及文件传输的主要功能,但是也各有各的特色,比如ICQ的巨大客户群,MSN的个性化表情,YAHOO通的易操作性等。而QQ也具有一个相当方便的屏幕截图功能,另外就是,所有上述软件都实现了网络即时的视频,语音聊天功能。这些软件,在使用方面各有特色,在实现方面也各有所长,但基于这些产品正在商业运营阶段,其实现方式属于商业机密,具体细节不可能得知,但是它在大的方面无非就是各种利用各种平台上的网络通信接口,建构基于下层TCP/IP,或者UDP/IP协议的软件产品。在局域网内,这些功能的实现跟广域网相比更加简单,因为局域网的网络结构本身比广域网要复杂,但是又可以借些理解网络协议,以及网络通信工具的实现原理,所以仍然极具研究价值。
1.3本文的主要工作
本文主要工作是设计一个基于WINDOWS平台的局域网即时聊天工具,然后阐述本软件的功能、特点及使用方法,并详细阐述开发本软件所用的相关技术,具体分析本软件的各个模块的功能及实现方法,说明本软件的设计思想及方法。
1.4开发平台与技术的选择及介绍
1.4.1 开发环境的介绍
我所设计的是一个面向中小型机构内部通信需求的局域网即时信息软件,要在短时间内开发出来并且要满足客户要求,无论是硬件还是软件都要选择合适,要求如下:开发设备应该完备;开发机器的性能必须稳定;操作系统的选择必须恬当;开发出的程序可以在尽可能多的平台上运行;要求运行机配置尽可能低档。对此,我们选择的硬件环境和软件环境如下:
(1) 硬件环境
开发该系统应尽可能采用高档的硬件。因此,在应用时应采用更好的配置。
处理器:Intel Pentium PIII或更高处理器。
内存:128MB或更高。
网络:局域网。
(2) 软件环境
选择好的操作系统和好的编程语言是系统优劣的关键,我们要求系统在尽可能多的环境下运行,故选择Windows XP平台,对于一些无法在98中运行的API函数,一律不采用,并采取优化的算法编写程序。因VC6.0具有友好的集成开发界面、面向对象的可视化开发模式、良好的数据库及多媒体应用支持以及高效的软件开发与程序运行,功能更大,开发效率更高,不仅是网络环境下的优秀前端开发语言和工具,也是服务器端Web编程的优秀工具。加之我本人对本系统的操作最为熟练,所以选择该平台为开发环境。
操作系统:Windows XP或Window2000。
开发工具:VC++6.0。
1.4.2 WINDOWS SOCKETS网络编程接口概述
既然选定了WINDOWS平台,而又要开发网络通信程序,所以可以选择WINDOWS的SOCKETS编程接口,Windows Sockets是一套开放的、支持多种协议的Windows下的网络编程接口。现在的Winsock已经基本上实现了与协议无关,你可以使用Winsock来调用多种协议的功能,但较常使用的是TCP/IP协议。Winsockets无疑是我们进行网络编程的利器[7]。
1.4.3 VC++6.0开发平台简介
开发平台我选用了VC6.0,因为一直以来都使用VC6进行学习,对这个IDE最为熟悉,再者VC同样是由微软开发的系统,与其操作系统,网络接口具有最为密切的契合优点,所以选择了VC6.0。
第2章 需求分析及可行性研究
2.1需求分析
2.1.1时间要求
本项目作为大学本科毕业设计题目,从3月5号接受选题开始,在5月15号之前完成系统设计,编码实现工作,在6月3号之前完成毕业设计论文初稿,6月18号之前最终完成论文。
2.1.2功能要求
这个程序要实现
(1)程序启动之后就能看到当前哪些机器在线,哪些可以与之进行对等通信。
(2)一旦有某个网内的机器上线了,要有即时通知,并能及时更新用户界面中的用户列表。
(3)当双击某个列表项的时候,要弹出聊天对话框,可以在其中编辑要发送的聊天信息,并进行发送。
(4)聊天界面要人性化,下面是发送框,上面有已有聊天记录,并借助滚动条看到当次所有的聊天记录。
(5)当有人向我发送信息的时候,要弹出一个对话框,显示用户接收到的信息,并且知道是谁人所发,并且在当前对话框内进行信息的回复。
2.1.3系统基本流程图
图2-1 局域网聊天系统的系统流程图
2.1.4性能要求
首先要求程序要完全可靠,可以应付种种由于系统问题产生的错误,比如初始网络失败,对方突然下线等。要求提前设想到类似的尽可能多的可能发生的事件,做出相应的应对措施,并向用户提交简单易懂清晰明白的提示信息。
程序要有良好的容错性,当用户进行非法操作时或者系统本身出现问题时要能以最好的方式退出程序,避免发生程序假死现象。
开发文档要有好的易理解性,如果系统又要交由别人接手开发,或者自己由于种种原因需要进行二次开发,那么要保证以后能够清晰的理解整个系统的设计思路以及实现细节。
要求程序对所运行之系统的硬件条件要求尽可能低,运行时内存占用尽可能小,响应速度要尽可能快。并且不发生内存泄漏之类影响系统运行的错误事件。并且要求易于维护及扩展。所以应该采用模块化开发,各个模块之间不要有太多的联系,以免维护困难。
2.1.5测试环境规定
在开发过程中由开发人员自己,也就是我本人随时进行内部部分白盒测试,在开发完成以后,自己进行一个全面的白盒测试,然后请同学帮忙进行黑盒测试。
2.2可行性研究
(1)成本可行性分析
因为本软件只做开发学习使用,所以暂且不考虑经济成本及盈利问题。
(2)技术可行性分析
首先我已经搭建好开发所需要的软硬件平台,并进行了合理而完善的需求分析,做好了充分的前期准备工作,其次因为本程序的平台将基于WINDOWS,将要使用网络通信技术,而WINDOWS有完善成熟的网络通信接口,以及与VC开发环境的严密契合能力,加之相类似的更大规模的INTERNET通信工具产品也已有例在先,所以这个程序的开发可行性在技术上是完全可行的。
第3章 相关开发技术的原理性说明
3.1 win32编程原理及MFC框架
3.1.1 WIN32编程原理
所谓的Win32开发,就是在C语言的层面上,直接使用Win32 API开发Windows应用程序或者系统程序。虽说现在直接用Win32 API开发应用程序的人已经不多了,但是深入理解Windows系统程序设计原理,仍然是成为Windows开发高手的良好途径。所谓的Win32,其实是一个API规范,与UNIX系统编程接口标准POSIX是相对应的。下面是进行直接的WIN32 SDK方式编程的基本思路或者说是一个框架:
一个WINDOWS程序分为程序代码和UI(User Interface 用户接口)资源两大部份,两部份最后以RC编译程序整合为一个完整的EXE文件。所谓UI资源是指功能菜单、对话框、程序图标、光标形状等等东西。这些UI资源的实际内容(二进制代码)系借助各种工具产生,并以各种扩展名存在,如 .ico .bmp .cur等等。程序员必须在一个所谓的资源描述档(.rc )中描述它们。RC编译器( RC.EXE )读取RC 文件的描述后将所有UI资源文件集中制作出一个.RES 文件,再与程序代码结合在一起,这才是一个完整的 Windows可执行文件。如下页图3-1所示[4]。
与控制台程序相同的是,一个WIN32程序也必须有一个程序入口点,但是在这儿它不再叫main(),而叫做WinMain(),当WINDOWS的SHELL检测到用户欲执行一个EXE程序,就会调用加载器把程序进行加载,然后调用C startup code,后者再调用WinMain(),程序的执行就开始了,WinMain()函数的原型为:int CALLBACK WinMain( HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow);
图3-1 32位WINDOWS程序的开发流程[4]
下面程序必须进行必要的初始化工作-产生窗口,第一步是注册一个窗口类:用API函数:RegisterClass(),而这个函数需要一个已经定义好的系统结构:WNDCLASS,这个结构里面定义了窗口的种种属性,需要自己定义,但是许多属性都有默认值。然后调用CreateWindow()函数来产生具有上述定义属性的已注册窗口,但是需要注意的是它只是生成窗口,但并不显示之,所以还需要调用一个函数ShowWindow()将它显示在屏幕上,做完这些初始化工作以后,系统将进入消息循环:
while (GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
DispatchMessage(&msg);}
当消息循环捕捉到消息以后将交由窗口函数WndProc()窗口函数进行相应的处理。这样,一个基于消息事件驱动的WIN32程序的雏形就建立了起来。
3.1.2 MFC框架
由上面的介绍可以看出,直接用API函数开发一个WIN32程序是相当麻烦的,有好多既定的重复性的工作要做,所以微软就用C++的类机制将绝大部分的API函数进行了封装,构成了类,并且将基本的流程也封装在类机制下面,大大简化了WIN32开的的复杂性,尤其是在开发比较大型程序的时候这个便宜性更会得以体现。它就是Microsoft Foundation Classes,简称为MFC,可以说它是VC开发环境的一个核心构件。MFC构架了一个庞大的类体系结构,在4.0时代就多达189个类,程序代码达252个文件,58个头文件,共10MB之多,MFC4.2时又多加了29个类,但是最为主干的是下面类结构示图2-2所示的一些类:[4]
图3-2 MFC类框架主体
构建一个基于MFC框架的程序,可以使用MFC的向导程序,但首先要明白,一个基于MFC的程序可以有几种类型:基于单文档结构的程序,基于多文档结构的程序以及基于对话框的应用程序,不同类型的程序具有不同的程序属性。使用其向导以及控件编程,使得不论是界面编写,还是程序内核设计,都更加的简单。其中有合理的消息映射机制,有方便的运行时类型识别功能,更有文档/视图结构设计,文档串行化功能等非常多的优秀功能。
3.2 TCP/IP 协议及WINDOWS SOCKETS网络编程接口
3.2.1 TCP/IP协议简介
TCP/IP协议实际上就是在物理网上的一组完整的网络协议。其中TCP是提供传输层服务,而IP则是提供网络层服务。TCP/IP主要包括以下协议:
IP:网间协议(Internet Protocol) 负责主机间数据的路由和网络上数据的存储。同时为ICMP,TCP,UDP提供分组发送服务。用户进程通常不需要涉及这一层。
ICMP:网间报文控制协议(Internet Control Message Protocol)
此协议处理网关和主机的差错和传送控制。
TCP: 传输控制协议(Transmission Control Protocol)
这是一种提供给用户进程的可靠的全双工字节流面向连接的协议。它要为
用户进程提供虚电路服务,并为数据可靠传输建立检查。
TCP/IP协议的核心部分是传输层协议(TCP、UDP),网络层协议(IP)和物
理接口层,这三层通常是在操作系统内核中实现。因此用户一般不涉及。编程时,
编程界面有两种形式:一、是由内核直接提供的系统调用;二、使用以库函数
方式提供的各种函数。前者为核内实现,后者为核外实现。用户服务要通过核外
的应用程序才能实现,所以要使用套接字(socket)来实现。
因为在本设计中使用了ICMP协议进行扫描局域网功能的实现,所以对ICMP进行进一步描述:
IP协议是一种不可靠的协议,无法进行差错控制。但IP协议可以借助其他协议来实现这一功能,ICMP就是其中最常用的协议之一。ICMP(Internet Control Messages Protocol, 网间控制报文协议)允许主机或路由器报告差错情况和提供有关异常情况的报告。一般来说,ICMP报文提供针对网络层的错误诊断、拥塞控制、路径控制和查询服务四项大的功能。如,当一个分组无法到达目的站点或TTL超时后,路由器就会丢弃此分组,并向源站点返回一个目的站点不可到达的ICMP报文。ICMP报文大体可以分为两种类型,即ICMP差错报文和ICMP询问报文。但细分又可分为很多类型,如图3-3所示:
ICMP报文被封装在IP数据报内部传输。如下图2-4所示,是ICMP回射请求和应答报文头部格式。各种ICMP报文的前32bits都一样,它们是:8bits类型和8bits代码字段:一起决定了ICMP报文的类型。常见的有:类型8、代码0:回射请求。类型0、代码0:回射应答。类型11、代码0:超时。16bits校验和字段:包括数据在内的整个ICMP数据包的校验和,其计算方法和IP头部校验和的计算方法是一样的。
图3-4 ICMP回射请求和应答报文头部格式
对于ICMP回射请求和应答报文来说,接下来是16bits标识符字段:用于标识本ICMP进程。最后是16bits序列号字段:用于判断回射应答数据报。
下面是ICMP不可到达报文的头部格式:
图3-5 ICMP不可到达报文头部格式
由于篇幅有限,这里不再分析其他类型ICMP协议数据包的格式。
简略的说,ICMP协议消息包含永远不会变化的三个字段,随后是ICMP数据,然后是引发此消息的源IP数据包包头。不会变化的三个字段中,前8个字节包含ICMP类型(主要类型)、第二个字段包含了类型代码、第三个字段是ICMP消息校验值。
我们需要认识到,ICMP协议在某些情况下不会发送错误信息。ICMP不会对ICMP信息做出响应。如果ICMP回应其它ICMP消息,这些消息的数量会爆炸性增长而演变为一场ICMP消息风暴。为了防止出现广播风暴,ICMP消息也不会回应一个广播或者多播地址。
最有用的ICMP数据包类型“目标不可达”(类型三)的消息。错误消息一般由路由器生成,并且发送给数据包的来源。大多数错误信息还将发送给与发送的数据包有关的应用程序。在这种情况下,TCP协议将广泛使用ICMP协议。
在本设计当中就是使用了ICMP来实现了一个PING功能,来检测局域网上的哪些机器当前处于可以到达状态的,ICMP回射请求和ICMP回射应答报文是配合工作的。当源主机向目标主机发送了ICMP回射请求数据包后,它期待着目标主机的回答。目标主机在收到一个ICMP回射请求数据包后,它会交换源、目的主机的地址,然后将收到的ICMP回射请求数据包中的数据部分原封不动地封装在自己的ICMP回射应答数据包中,然后发回给发送ICMP回射请求的一方。如果校验正确,发送者便认为目标主机的回射服务正常,也即物理连接畅通。
综上所述,只要网路之间能支持 IP ,那就可透过 ICMP 进行错误侦测与回报。如果要查看具体的细节情况,可以查阅RFC文件,与ICMP相关的文件有:RFC-792﹑RFC-896﹑RFC-950等。
3.2.2 WINDOWS SOCKETS网络编程接口概述
在网络编程中最常用的方案便是Client/Server (客户机/服务器)模型。在这种方案中客户应用程序向服务器程序请求服务。一个服务程序通常在一个众所周知的地址监听对服务的请求,也就是说,服务进程一直处于休眠状态,直到一个客户向这个服务的地址提出了连接请求。在这个时刻,服务程序被"惊醒"并且为客户提供服务-对客户的请求作出适当的反应。
为了方便这种Client/Server模型的网络编程,90年代初,由Microsoft联合了其他几家公司共同制定了一套WINDOWS下的网络编程接口,即Windows Sockets规范,它不是一种网络协议,而是一套开放的、支持多种协议的Windows下的网络编程接口。现在的Winsock已经基本上实现了与协议无关,你可以使用Winsock来调用多种协议的功能,但较常使用的是TCP/IP协议。
Socket实际在计算机中提供了一个通信端口,可以通过这个端口与任何一个具有Socket接口的计算机通信。应用程序在网络上传输,接收的信息都通过这个Socket接口来实现。如下图2-7所示:
图3-7 面向连接的套接字的系统调用时序图
微软为Visual C++定义了Winsock类如CAsyncSocket类和派生于CAsyncSocket 的CSocket类,它们简单易用,我们当然可以使用这些类来实现自己的网络程序,但是为了更好的了解Winsock API编程技术,本设计中将使用底层的API函数实现 Winsock 平台的即时通信工具。
在VC中进行WINSOCK的API编程开发的时候,需要在项目中使用下面的三个文件,否则会出现编译错误。
(1) WINSOCK.H: 这是WINSOCK API的头文件,需要包含在项目中。
(2) WSOCK32.LIB: WINSOCK API连接库文件。
(3) WINSOCK.DLL: WINSOCK的动态连接库,位于WINDOWS的安装目录下。
3.3多线程编程技术
3.3.1进程及线程概述
进程和线程都是操作系统的概念。进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭。
线程是进程内部的一个执行单元。系统创建好进程后,实际上就启动执行了该进程的主执行线程,主执行线程以函数地址形式,比如说main或WinMain函数,将程序的启动点提供给Windows系统。主执行线程终止了,进程也就随之终止。
每一个进程至少有一个主执行线程,它无需由用户去主动创建,是由系统自动创建的。用户根据需要在应用程序中创建其它线程,多个线程并发地运行于同一个进程中。一个进程中的所有线程都在该进程的虚拟地址空间中,共同使用这些虚拟地址空间、全局变量和系统资源,所以线程间的通讯非常方便,多线程技术的应用也较为广泛。
多线程可以实现并行处理,避免了某项任务长时间占用CPU时间。要说明的一点是,目前大多数的计算机都是单处理器(CPU)的,为了运行所有这些线程,操作系统为每个独立线程安排一些CPU时间,操作系统以轮换方式向线程提供时间片,这就给人一种假象,好象这些线程都在同时运行。由此可见,如果两个非常活跃的线程为了抢夺对CPU的控制权,在线程切换时会消耗很多的CPU资源,反而会降低系统的性能。这一点在多线程编程时应该注意。
Win32 SDK函数支持进行多线程的程序设计,并提供了操作系统原理中的各种同步、互斥和临界区等操作。Visual C++ 6.0中,使用MFC类库也实现了多线程的程序设计,使得多线程编程更加方便。
3.3.2 Win32 API对多线程编程的支持
Win32 提供了一系列的API函数来完成线程的创建、挂起、恢复、终结以及通信等工作。下面将选取其中的一些重要函数进行说明。
(1) HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId);
该函数在其调用进程的进程空间里创建一个新的线程,并返回已建线程的句柄。
(2) DWORD SuspendThread(HANDLE hThread);
该函数用于挂起指定的线程,如果函数执行成功,则线程的执行被终止。
(3) DWORD ResumeThread(HANDLE hThread);
该函数用于结束线程的挂起状态,执行线程。
(4) VOID ExitThread(DWORD dwExitCode);
该函数用于线程终结自身的执行,主要在线程的执行函数中被调用。其中参数dwExitCode用来设置线程的退出码。
(5) BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode);
一般情况下,线程运行结束之后,线程函数正常返回,但是应用程序可以调用TerminateThread强行终止某一线程的执行。
使用TerminateThread()终止某个线程的执行是不安全的,可能会引起系统不稳定;虽然该函数立即终止线程的执行,但并不释放线程所占用的资源。因此,一般不建议使用该函数。
(6) BOOL PostThreadMessage(DWORD idThread,UINT Msg,WPARAM wParam,LPARAM lParam);
该函数将一条消息放入到指定线程的消息队列中,并且不等到消息被该线程处理时便返回。
调用该函数时,如果即将接收消息的线程没有创建消息循环,则该函数执行失败。