学位论文—基于tcp的服务器客户端程序设计.doc

上传人:知****量 文档编号:86300908 上传时间:2023-04-14 格式:DOC 页数:20 大小:354KB
返回 下载 相关 举报
学位论文—基于tcp的服务器客户端程序设计.doc_第1页
第1页 / 共20页
学位论文—基于tcp的服务器客户端程序设计.doc_第2页
第2页 / 共20页
点击查看更多>>
资源描述

《学位论文—基于tcp的服务器客户端程序设计.doc》由会员分享,可在线阅读,更多相关《学位论文—基于tcp的服务器客户端程序设计.doc(20页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、重庆交通大学信息科学与工程学院 课程设计实验报告 专 业: 学 号: 姓 名: 实验室(中心): 信息技术软件实验室 指 导 教 师 : 实验完成时间: 2015 年 1 月 12 日目录一、 实验设计题目-2二、 实验目的-2三、 实验设计要求-2四、 课程设计条件-2五、实验设计分析-4六、实验设计流程图-9七、结果分析-13八、实验心得体会-14九、实验主要代码-1517一、 实验设计题目基于TCP的服务器/客户端程序设计二、 实验目的1、 理解客户端与服务器模型的工作原理。2、 掌握套接字的概念。3、 掌握TCP协议,基于TCP协议来设计此客户端/服务器程序。4、 通过设计面向连接的数

2、据流传输服务程序,加深对面向连接的服务程序工作流程和基本框架的理解。三、 实验设计要求1)任选一种编程语言,编程实现面向连接的客户/服务器程序,客户端、服务器端分别编程;2) 编程要充分体现服务器端与客户端的连接建立、数据传输、连接释放的过程;四、课程设计条件 本次课程设计我采用的是JAVA语言,实现客户端和服务器之间的联系。 Java 编程语言的风格十分接近C、C+语言。Java是一个纯的面向对象的程序设计语言,它继承了 C+语言面向对象技术的核心。Java舍弃了C +语言中容易引起错误的指针(以引用取代)、运算符重载(operator overloading)、多重继承(以接口取代)等特性

3、,增加了垃圾回收器功能用于回收不再被引用的对象所占据的内存空间,使得程序员不用再为内存管理而担忧。在 Java 1.5 版本中,Java 又引入了泛型编程(Generic Programming)、类型安全的枚举、不定长参数和自动装/拆箱等语言特性。Java 不同于一般的编译执行计算机语言和解释执行计算机语言。它首先将源代码编译成二进制字节码(bytecode),然后依赖各种不同平台上的虚拟机来解释执行字节码。从而实现了“一次编译、到处执行”的跨平台特性。不过,每次的执行编译后的字节码需要消耗一定的时间,这同时也在一定程度上降低了 Java 程序的运行效率。Java语言的变量声明,操作符形式,

4、参数传递,流程控制等方面和C语言,C+语言完全相同.尽管如此,Java和C语言,C+语言又有许多差别,主要表现在如下几个方面:Java中对内存的分配是动态的,它采用面向对象的机制,采用运算符new为每个对象分配内存空间,而且,实际内存还会随程序运行情况而改变。程序运行中 Java系统自动对内存进行扫描,对长期不用的空间作为”垃圾”进行收集,使得系统资源得到更充分地利用.按照这种机制,程序员不必关注内存管理问题,这使Java程序的编写变得简单明了,并且避免了由于内存管理方面的差错而导致系统出问题。而C语言通过malloc()和free()这两个库函数来分别实现分配内存和释放内存空间的,C+语言中

5、则通过运算符new和delete来分配和释放内存。在C和C+这种机制中,程序员必须非常仔细地处理内存的使用问题。一方面,如果对己释放的内存再作释放或者对未曾分配的内存作释放,都会造成死机;而另一方面,如果对长期不用的或不再使用的内存不释放,则会浪费系统资源,甚至因此造成资源枯竭。 Java不在所有类之外定义全局变量,而是在某个类中定义一种公用静态的变量来完成全局变量的功能。 Java不用goto语句,而是用try-catch-finally异常处理语句来代替goto语句处理出错的功能。 Java不支持头文件,而C和C+语言中都用头文件来定义类的原型,全局变量,库函数等,这种采用头文件的结构使得

6、系统的运行维护相当繁杂。 Java不支持宏定义,而是使用关键字final来定义常量,在C+中则采用宏定义来实现常量定义,这不利于程序的可读性。 Java对每种数据类型都分配固定长度。比如,在Java中,int类型总是32位的,而在C和C+中,对于不同的平台,同一个数据类型分配不同的字节数,同样是int类型,在PC机中为二字节即16位,而在VAX-11中,则为32位.这使得C语言造成不可移植性,而Java则具有跨平台性(平台无关性)。Java语言编写的类库可以在其它平台的Java应用程序中使用,而不像C+语言必须依赖于Windows平台。五、实验设计分析 本实验的设计是基于TCP/IP协议的程序

7、时,传输层使用TCP协议,它的最大特点是在通信之前要在客户和服务器之间先建立连接,在数据传输完成后要关闭连接,释放网络资源。对于TCP协议,主要有以下特点:(1) TCP是面向连接的运输层协议。应用程序在使用TCP协议之前,必须先建立TCP连接。在传送数据完毕后,必须释放已经建立的TCP连接。也就是说,应用进程之间的通信好像在“打电话”:通话前要先拨号建立连接,通话结束后要挂机释放连接。(2) 每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的,即一对一的连接。(3) TCP提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复,并且按序到达。(4) TCP提供全双工

8、通信。TCP允许通信双方的应用进程在任何时候都能发送数据。TCP连接的两端都设有发送缓存和接受缓存,用来临时存放双向通信的数据。在发送时,应用程序在把数据传送到TCP的缓存后,就可以做自己的事,而TCP在合适的时候把数据发送出去。在接收时,TCP把收到的数据放入缓存,上层的应用进程在合适的时候读取缓存中的数据。(5) 面向字节流。TCP中的“流”指的是流入到进程或从进程流出的字节序列。虽然应用程序和TCP的交互是一次一个数据块,但TCP把应用程序交下来的数据看成仅仅是一连串的无结构的字节流。TCP不保证接收方应用程序所收到的数据块和发送方应用程序所发出的数据块具有对应大小的关系。但接收方应用程

9、序收到的字节流必须和发送方应用程序发出的字节流完全一样。TCP连接是一条虚连接而不是一条真正的物理连接。TCP报文段先要传送到IP层,加上IP首部后,再传送到数据链路层。再加上数据链路层的首部和尾部后,才离开主机发送到物理链路。每一条TCP连接有两个端点,这个端点就是套接字(socket),端口号拼接到IP地址即构成了套接字,每一条TCP连接唯一地被通信两端的两个端点,即两个套接字所确定。同一个IP地址可以有多个不同的TCP连接,而同一个端口号也可以出现在不同的TCP连接中。TCP是面向连接的协议。运输连接是用来传送TCP报文的。TCP运输连接的建立和释放是每一次面向连接的通信中必不可少的进程

10、。因此,运输连接就有三个阶段,即:连接建立、数据传送和连接释放。运输连接的管理就是使运输连接的建立和释放都能正常的进行。在TCP连接建立过程中要解决一下三个问题:(1) 要使每一方能够确知对方的存在。(2) 要允许双方协商一些参数(如最大窗口值、是否使用窗口扩大选项和时间戳选项及服务质量等)。(3) 能够对运输实体资源(如缓存大小、连接表中的项目等)进行分配。 TCP连接的建立采用客户服务器方式。主动发起连接建立的应用进程叫做客户,而被动等待连接建立的应用进程叫做服务器。CLOSEDLISTENSYN-RCVDESTAB-LISHEDCLOSEDSYN-SENTESTAB-LISHED服务器B

11、客户A 下图是TCP连接建立的过程。 数据传送 主机A运行的是TCP客户程序,而B运行TCP服务器程序。最初两端的TCP进程都处于CLOSED状态。A是主动打开连接,而B是被动打开连接。 B的TCP服务器进程先创建传输控制块TCB,准备接受客户进程的连接请求。然后服务器进程就处于LISTEN状态,等待客户的连接请求。如有,即做出响应。A的TCP客户进程也是首先创建传输控制模块TCB,然后向B发出连接请求报文段,这时首部中的同步位SYN=1,同时选择一个初始序号seq=x。SYN报文段不能携带数据,但要消耗掉一个序号。这时,TCP客户进程进入SYN-SENT状态。B收到连接请求报文段后,如同意建

12、立连接,则向A发送确认。在确认报文段中应把SYN位和ACK位都置1,确认号是ack=x+1,同时也为自己选择一个初始序号seq=y。这个报文段也不能携带数据,但同样要消耗掉一个序号。这时TCP服务器进程进入SYN-RCVD状态。TCP客户进程收到B的确认后,还要向B给出确认。确认报文段的ACK置1,确认号ack=y+1,而自己的序号seq=x+1,ACK报文段可以携带数据,但如果不携带数据则不消耗序号,在这种情况下,下一个数据报文段的序号仍是seq=x+1。这时,TCP连接已经建立,A进入ESTABLISHED状态。当B收到A确认后,也进入ESTABLISHED状态,这个过程就是三次握手。数据

13、传输结束后,通信双方都可释放连接。现在A和B都处ESTABLISHED状态。A的应用进程先向其TCP发出连接释放报文段,并停止再发送数据,主动关闭TCP连接。A把连接释放报文段首部的终止控制位FIN置1,其序号seq=u,它等于前面已传送过的数据的最后的一个字节的序号加1。这时A进入FIN-WAIT-1状态,等待B的确认。FIN报文段即使不携带数据,它也消耗掉一个序号。B收到连接释放报文段后即发出确认,确认号是ack=u+1,而这个报文段自己的序号是v,等于B前面已传送过的数据的最后一个字节的序号加1。然后B就进入CLOSE-WAIT状态。TCP服务器进程这时应停止高层应用进程,因而从A到B这

14、个方向的连接就释放了,这时的TCP连接处于半关闭状态,即A已经没有数据要发送了,但B若发送数据,A仍要接收。也就是说,从B到A这个方向的连接并为关闭,这个状态可能会持续一些时间。A收到来自B的确认后,就进入FIN-WAIT-2状态,等待B发出的连接释放报文段。若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接。这时B发出的连接释放报文段必须使FIN=1。假定B的序号为w,B还必须重复上次已发送过的确认号ack=u+1。这是B就进入LAST-ACK状态,等待A的确认。A在收到B的连接释放报文段后,必须对此发出确认。在确认报文段中把ACK置1,确认号ack=w+1,而自己的序号是seq=

15、u+1。然后进入到TIME-WAIT状态。要经过4分钟才能进入到CLOSED状态,才能开始建立下一个新的连接,当A撤销相应的传输控制块TCB后,就结束了这次的TCP连接。这个过程就是TCP连接释放过程的四次握手。TCP的连接释放采用四次握手机制。任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后就进入半关闭状态。当另一方也没有数据再发送时,则发送连接通知,对方确认后就完全关闭了TCP连接。如下图所示。服务器B客户 AESTAB-LISHEDCLOSE-WAITLAST-ACKCLOSEDESTAB-LISHEDFIN-WAIT-1FIN-WAIT-2TIME-WAITCLOSED主

16、动 数据传送被动 TCP虽然是面向字节流的,但TCP传送的数据单元却是报文段。一个TCP报文段分为首部和数据两部分,而TCP的全部功能都体现在它的首部中各字段的作用。因此,只有弄清TCP首部各字段的作用才能掌握TCP的工作原理。 TCP报文段首部的前20个字节是固定的,后面有4n字节是根据需要而增加的选项。因此TCP首部的最小长度是20字节。如下图所示。对于TCP报文段中的序号部分,它是占了4 字节,TCP是面向字节流的,在下一个TCP连接中传送的字节流中的每一个字节都按顺序编号,整个要传送的字节流的起始序号必须在连接建立时设置。首部中的序号字段值则指的是本报文段所发送的数据的第一个字节的序号

17、。例如,一报文段的序号字段值是301,而携带的数据共有100字节。这就表明:本报文段的数据的第一个字节的序号是301,最后一个字节的序号是400。显然,下一个报文段的数据序号应该从401开始。对于确认号,是占4个字节,是期望收到对方下一个报文段的第一个数据字节的序号。例如,B正确收到了A发送过来的一个报文段,其序号字段值是501,而数据长度是200字节,这表明B正确收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701。还有一个比较重要的部分就是校验和。是占2个字节,校验和字段检验的范围包括首部和数据这两部分。在计算校

18、验和时,要在TCP报文段的前面加上12字节的伪首部。伪首部的格式与UDP用户数据报的伪首部一样。但应把伪首部第4个字段中的17改为6,把第5字段中的UDP长度改为TCP长度,接收方收到此报文段后,仍要加上这个伪首部来计算校验和。TCP可靠传输的实现是已字节为单位的滑动窗口。发送窗口是根据接收窗口设置的,但在同一时刻,发送窗口并不总是和接受窗口一样大。这是因为通过网络传送窗口值需要经历一定的时间滞后。发送方还可以根据网络当时的拥塞情况适当的减小自己的发送窗口值。对不按序到达的数据是先临时存放在接受窗口中,等到字节流中所缺少的字节收到后,再按序交付上层的应用进程。TCP要求接收方必须有累积确认的功

19、能,这样可以减少传输开销。接收方可以在合适的时候发送确认,也可以在自己有数据要发送时把确认信息顺便捎带上。但是,接收方也不应该过分推迟发送确认,否则会导致发送方不必要的重传,这回浪费网络的资源。其次,捎带确认实际上并不经常发生,因为大多数应用程序不同时在两个方向上发送数据。六、实验设计流程图本课程设计采用的是JAVA语言编制的,在JAVA中,客户端和服务器之间的通信编程一般是基于socket实现的。Socket是两个实体之间进行通信的有效端点,通过socket可以获得源IP地址和源端口、终点IP地址和终点端口,并创建一个能被多人使用的分布式应用程序,实现与服务器的双向自由通信。本设计是一对多的

20、socket通信,即一个服务器对应多个客户端,采用的方法是将socket对象放置在线程中,这样当每一个socket对象执行完任务后,只有包含该socket对象的线程会终止,对其他线程没有任何影响。服务器:服务器是用来接收客户端的各种信息的,并把信息传送回给客户端。网络应用程序一般是以客户机/服务器的模型的方式工作的。因特网是客户机/服务器模型的一个典型应用。在这种工作方式中,一个服务器程序通常事先启动,并在一个熟知端口侦听对服务器的请求。当客户机应用程序需要某种服务时,需向提供这种服务的服务器发出请求,服务器在接收到请求后,向客户机发出相应请求信息。这样客户机应用程序和服务器程序之间便建立了通

21、信连接此后可以进行数据通信。通信任务完成后需要关闭它们之间的通信连接。 开始客户端:设置一个新的socket,定义端口号为5500,连接到本机将输入数据流连接到socket上将数据输出流连接到socket上打印输入待求平方值,输入bye结束将输入数据流读入到缓存中进行一个while死循环读入用户的写入写到socket中写到socket中,清空缓存区,立即发送,从socket中读数据输入为bye?NY返回结果 结束服务器线程:相当于服务器里面的socket的一个集合,执行一次,就运行一个socket对象,当每一个socket对象执行完任务后,只有包含该socket对象的线程会终止,对其他线程没有

22、任何影响。 结束输出结果进行平方运算将接收到的值打印出来清空缓存区,立即发送将bye写入到socket中Y数据为bye?读缓存中的数据执行while死循环在run()方法中与客户端通信启动run()方法 开始在构造方法中为每个套接字连接输入和输出流七、结果分析首先,运行的是服务器的主程序,由显示可知,服务器已处于等待连接状态。然后运行的是客户端的程序代码。可知,服务器与客户端已建立了连接。此连接的建立是通过服务器和客户端都有一个端口号一样的socket,这样才可以建立连接。连接建立以后,就要开始进行数据传输了,通过客户端输入要传送的数据,此数据通过客户端和服务器之间建立的连接进入到服务器。在服

23、务器中又调用线程的程序,来进行数据的出来,本设计是对数据进行求平方,并把结果返回给客户端。在客户端输入bye之后,便删除了所建立的连接。多次运行客户端的程序,即可实现一对多的通信过程,一个服务器对应多个客户端,每次执行完一次,便终止此socket对象,下次执行的时候,再进行另外一个线程。八、实验心得体会 经过不断的修改与查找资料,终于完成了此次课程设计实验,虽说这次设计的实验不是很大型,但是还是学到了很多东西,收获颇丰,不仅学习到了一些新的知识,回顾了一些以前快要遗忘的知识点,而且是自己的学习目标更加明确,学习方法更加完善,也体会到了软件开发的趣味,更加清楚的认识到了自己在软件开发及学习上的不

24、足之处。 此次设计的是服务器与客户端之间进行通信,老师在我们设计之前讲解的很清晰,使得我们大家操作起来比较娴熟。让我感觉到了软件编程的趣味性和实用性,虽说一些技术我们在课堂上也曾学习过,但是大都停留在理论基础上,实际开发很少,而这次实验给了我们一个很好的边学习边实践的机会,对我们深入学习这些技术有很大的帮助,深刻体会到了这些技术的实用性。这次课程设计的编程我采用的是JAVA的语言,虽说以前没有学习过这门语言,可是经过两个多星期的查找资料与询问同学,大致上对于JAVA的编程方法还是有了一定的理解和认识。JAVA的功能很强大,有很多要实现的功能,只要通过调用一些函数就可以实现了,确实是很好用的一门

25、语言。每当自己成功调试一段代码或者通过自己的努力克服一个技术困难,都颇有收获感。这次实验让我们体验了软件的实用性,发现自己的不足,增加了一定的编程经验。结束了此次实验,让我发现我对我们专业有了新的认识,通过这次实验,我了解到,要真真正正掌握到计算机程序不是一件简单的事情,但真正掌握后,它带给我们的将是无穷的便捷与科技,我会努力学习计算机的!九、实验主要代码【服务器线程程序】package cn.edu.cqjtu.socket2;import java.io.*;import .*;public class ServerThread extends Threadprivate Socket s

26、;private DataInputStream is;/输入数据流private DataOutputStream os;/输出数据流/在构造方法中为每个套接字连接输入和输出流public ServerThread(Socket socket) throws IOExceptionsuper();s=socket;is=new DataInputStream(s.getInputStream();os=new DataOutputStream(s.getOutputStream();start(); /启动run()方法/在run()方法中与客户端通信public void run()try

27、String str;double result,zhi;boolean NotEnd=true;while(NotEnd)str=is.readUTF();/读数据if(!str.equals(bye)zhi=Double.parseDouble(str);System.out.println(接收到的值为:+zhi);result=zhi*zhi;str=Double.toString(result);os.writeUTF(str);/写入数据os.flush();/清空缓存System.out.println(平方值+str+已经发送);elseNotEnd=false;os.writ

28、eUTF(bye);os.flush();is.close();os.close();s.close();catch(IOException e)e.printStackTrace();【服务器主程序】package cn.edu.cqjtu.socket2;import java.io.*;import .*;public class MultiServer public static void main(Stringargs)trySystem.out.println(等待连接);ServerSocket serverSocket=new ServerSocket(5500);Socket

29、 s=null;while(true)/等待客户端的请求s=serverSocket.accept();/每次请求都等待一个线程来处理new ServerThread(s);catch(IOException e)e.printStackTrace();【客户端程序】package cn.edu.cqjtu.socket2;import java.io.*;import .*;public class Client public static void main(Stringargs)try/连接到本机,端口号为5500Socket s=new Socket(localhost,5500);/

30、将数据输入流连接到socket上DataInputStream is=new DataInputStream(s.getInputStream();/将数据输出流连接到socket上DataOutputStream os=new DataOutputStream(s.getOutputStream();System.out.println(输入待求平方值,输入bye结束。);String outStr,inStr;boolean NotEnd=true;BufferedReader buf=new BufferedReader(new InputStreamReader(System.in);/反复读用户的数据并计算while(NotEnd)outStr=buf.readLine();/读入用户的数据 os.writeUTF(outStr);/写入socket中 os.flush();/清空缓存区,立即发送 inStr=is.readUTF();/从socket中读数据 if(!inStr.equals(bye) System.out.println(返回结果:+inStr); else NotEnd=false;is.close();os.close();s.close();catch(IOException e)e.printStackTrace();

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 教案示例

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com