1、 网络协议编程课程设计 长沙理工大学计算机与通信工程学院 《网络协议编程》课程设计报告 院 系 计算机与通信工程学院 专 业 网络工程 班 级 网络1101班 学 号 201158080110 学生姓名 赵思雨 指导教师 谢晓巍
2、 课程成绩 完成日期 2014年9月24日 课程设计成绩评定 院 系 计算机与通信工程 专 业 网络工程 班 级 网络1101班 学 号 201158080110 学生姓名 赵思雨 指导教师 谢晓巍 指导教师对学生在课程设计中的评价 评分项目 优 良 中 及格 不及格 学习态度与遵守纪律情况 课程设计完成情况 课程设计报告的质量
3、 指导教师成绩 指导教师签字 年 月 日 课程设计答辩组对学生在课程设计中的评价 评分项目 优 良 中 及格 不及格 课程设计完成情况 课程设计报告的质量 课程设计答辩 答辩组成绩 答辩组长签字 年 月 日 课程设计综合成绩 注:课程设计综合成绩=指导教师成绩×60%+答辩组成绩×40% 课程设计任务书 计算机与
4、通信工程 学院 网络工程 专业 课程名称 网络协议编程课程设计 时间 2014年9月15日—9月28日 学生姓名 赵思雨 指导老师 谢晓巍 题 目 基于UDP网络通信系统的服务端程序设计 主要内容: (1)理解UDP协议的基本功能和工作原理。 (2)培养运用理论知识解决实际问题的能力。 (3)理解UDP协议在Java编程语言中的具体体现。 (4)运用所学的知识,学会分析程序,并从实际上实现即时通讯的要求。 要求: (1)实现的是服务器和客户端的通讯。 (2)学会文献检索的基本方法和综合运用文献的能力。 (3)通过课程设计培养严谨的科
5、学态度,认真的工作作风和团队协作精神 应当提交的文件: (1)课程设计报告。 (2)课程设计附件(源程序、各类图纸、实验数据、仿真截图等实证材料)。 基于UDP网络通信系统的服务端程序设计 学生姓名:赵思雨 指导老师:谢晓巍 摘 要 随着网络技术的发展及人们生活的需求,网络聊天已越来越受到人们的青睐 。网络聊天已经成为人们工作生活中传递信息、交流感情的重要工具,给人们带来了很大的方便。 本课题是开发一个基于UDP的局域网聊天系统,运用软件工程的设计流程,综合运用数据库编程技术、Windows程序设计技术、网络通讯技术,此网络聊天工具采用客户端/服
6、务器(C/S)模式,客户端采用UDP与服务器连接,客户端与客户端之间通过UDP互相通讯。服务器端具有服务器端口设置,此聊天工具能实现多人聊天功能,适用于局域网使用的网络聊天工具,其操作简单,灵活性好,运行也比较稳定。 关键词 网络通讯;客户端/服务器模型;用户数据报协议;套接字 1 引 言 自进入信息化社会以来,人们的生活发生了翻天覆地的变化,所有这一切的实现都要归功于计算机网络。自从计算机网络出现以来,网络发展越来越迅速,其重要性更是不可估量。现在,网络已经进入到我们生活的各个角落,大到网上理财、网上会议、网上战争,小到上网购物、查找资料,网上聊天等,
7、可以说网络把我们的世界变“小”了,即使在天涯海角,我们也可以随时联系。一个最简单且应用最广泛的例子——网上聊天,就是最好的证明。本课程设计将基于UDP协议和局域网环境,使用Java语言实现一个即时网络通讯程序。 1.1背景介绍 随着计算机网络信息技术的日益发展和成熟,人们的生活因为网络而变得更多姿多彩,基于网络的通讯技术也如同雨后春笋般涌现到网络世界中。TCP协议和UDP协议是网络通讯的基本协议。而对于普通的信息交流,UDP协议则因为更方便简单,所以常常采用UDP协议开发这类即时通讯程序。 (1)理解UDP协议的基本功能和工作原理。 (2)培养运用理论知识解决实际问题的能力。 (
8、3)理解UDP协议在Java编程语言中的具体体现。 (4)运用所学的知识,学会分析程序,并从实际上实现即时通讯的要求。 1.2课程设计的目的 1.3课程设计的基本任务 本次课程设计是基于UDP协议的通讯程序,所以其基本任务就是要实现的是服务器和客户端的通讯,即服务器对端口进行监听,客户端发送数据给服务器,服务器接收。实现了这个过程,就达到了本次课程设计的目的。 2 设计原理 2.1 UDP协议原理 UDP协议的全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组
9、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天UDP仍然不失为一项非常实用和可行的网络传输层协议。 UDP是OSI参考模型中一种无连接的传输层协议,它主要用于不要求分组顺序到达的传输中,分组传输顺序的检查与排序由应用层完成,提供面向事务的简单不可靠信息传送服务。UDP 协议基本上是IP协议与上层协议的接口。U
10、DP协议适用端口分别运行在同一台设备上的多个应用程序。 与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。 UDP协议的主要作用是将网络数据流量压缩成数据包的形式。一个典型的数据包就是一个二进制数据的传输单位。每一个数据包的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。 UDP是无连接的,即发送数据之前不需要建立连接(当然发送数据结束时也没有连接可释放)因此减少了开销和发送数据之前的时延。 UDP使用的是尽最大努力交付,即不保证可靠交
11、付,因此主机不需要维持复杂的连接状态表。 UDP是面向报文的。发送方的UDP对应程序交下来的报文,在添加首部后就向下交付给IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。 UDP是定义用来在互连网络环境中提供数据报交换的计算机通信的协议。此协议默认是IP下层协议。此协议提供了向另一用户程序发送信息的最简便的协议机制,不需要连接确认和保护复制,所以在软件实现上比较简单,需要的内存空间比起TCP相对较小。 UDP包头由4个域组成,其中每个域各占用2个字节。 (1)源端口号(16位):UDP数据包的发送方使用的端口号。 (2)目标端口号(16位):UDP
12、数据包的接收方使用的端口号。UDP协议使用端口号为不同的应用保留其各自的数据传输通道。UDP和rap协议正是采用这一机制,实现对同一时刻内多项应用同时发送和接收数据的支持。 (3)数据报长度(16位)。数据报的长度是指包括报头和数据部分在内的总的字节数。理论上,包含报头在内的数据包的最大长度为65535字节。不过,一些实际应用往往会限制数据包的大小,有时会降低到8192字节。 (4)校验值(16位)。UDP协议使用包头中的校验值来保证数据的安全。 2.2客户端/服务器模式 客户机一方,UDP应用程序功能如下: (1) 打开通信信道(申请一套接字),并连接到服务器在主机的保留端口,该
13、端口对应服务器的UDP进程。 (2) 向服务器发出请求报文,等待接收应答。 (3) 从服务器方收到最终应答结果,或在不再请求时关闭信道并终止客户机进程。 服务器一方,UDP应用程序动作如下: (1) 打开通信信道(申请一套接字),通知本地主机在某一保留端口接收客户机请求。 (2) 等待客户请求到达指定端口。 (3) 接收到请求,启动一新进程处理用户请求,同时释放旧进程以响应新的客户请求,一旦服务完成,关闭新进程与客户的通信链路。 (4) 继续等待客户机请求。 (5) 如果不想响应客户机请求,关闭服务器进程 3.设计步骤 此次设计是编写一个基于UDP的即时通讯程序,要求双
14、方能够进行即时通讯,实现聊天和传输文件的功能。本课程设计主要负责的是通讯程序客户端的设计。其具体设计如下。 3.1 聊天模块设计流程图 服务器端设计程序得出当前服务器的地址 客户端输入所要连接的服务器地址 地址是否相同 输入客户端发送的信息 设置服务器端端口号为80 接收客户端发送的消息,发出服务器消息 设置客户端端口号为80 接收服务器发送到消息,发出客户端消息 接受客户端发送的消息,发出服务器消息 消息内容是否为NULL 结束通讯 即时通讯程序客户端/服务器端聊天模块设计流程图如图所示。
15、 图1-1 聊天模块流程图 3.2详细设计 根据UDP协议的基本特性以及Java语言编程特点,然后对比设计流程图,在Eclipse编程环境下编写出实现该即时聊天系统的程序,具体步骤如下: 1.打开Eclise创建一个Java工程,命名为UDPChat。 2.在Java工程目录下创建一个package,命名为UDPChat。 3.在此package目录下创建一个类,类名为Client,创建完之后弹出一个编辑窗口,在此编辑环境下编写客户端程序,其聊天模块服务器端核心程序如下: public class Server {
16、 public static void main(String[] args) { new UDPServer().start(); //启动服务器 } } class UDPServer extends Thread { public UDPServer() { } //缺省构造函数 public void run() { try { DatagramSocket socket = new DatagramSocket(80); //建立一个Socket连接,端口号为80 System.out.println("服务器IP地址为:" + InetA
17、ddress.getLocalHost().getHostAddress()); //得到服务器地址,并打印出来 //实现客户端和服务器端的连续通信 while (true) { // 接收 byte[] instr = new byte[200]; //定义数组,用来保存客户端发送来的数据 DatagramPacket receive = new DatagramPacket(instr, instr.length); socket.receive(receive); //接收客户机发过来的数据 String str
18、 = new String(receive.getData()); //提取数据 System.out.println("客户端消息:" + str.trim()); //打印客户机消息 // 发送 System.out.print("接收到的服务器消息:"); //打印消息 str = new BufferedReader(new InputStreamReader(System.in)).readLine(); //得到输入的数据 byte[] outstr = new byte[str.length()]; outstr
19、 = str.getBytes(); DatagramPacket send = new DatagramPacket(outstr,outstr.length, receive.getAddress(), receive.getPort()); //向客户机发送数据 socket.send(send); //执行发送 } } catch (Exception e) { //错误处理 e.printStackTrace(); } } 文件传输模块核心代码如下: public void run() {
20、 System.out.println("Connected from " + socket.getRemoteSocketAddress()); try { BufferedReader in = new BufferedReader( new InputStreamReader(socket.getInputStream())); //定义字符流 PrintWriter out = new PrintWriter(
21、 new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); //创建打印对象 String inputLine, outputLine; HandleInput handleInput = new HandleInput(); outputLine = handleInput.handle(null); out.pr
22、intln(outputLine); while((inputLine = in.readLine()) != null){ //读取信息 outputLine = handleInput.handle(inputLine); //每次读一行 out.println(outputLine); out.flush(); if(outputLine.equals("b
23、ye")) //结束标志 break; if(outputLine.equals("password:valid")){ //prepare for the transmission of the file Thread.sleep(2000); /线程休眠 InputStream fileInput = new FileInputStream(new F
24、ile(DEFAULT_FILE_NAME)); //创建字节输入流 OutputStream fileOutput = new DataOutputStream( new BufferedOutputStream(socket.getOutputStream())); //创建字节输出流 byte[] buf = new byte[2048];
25、 //transmit the file int num = fileInput.read(buf); while(num != -1){ fileOutput.write(buf, 0, num); fileOutput.flush(); num = fileInput.read(buf);
26、 } fileInput.close(); //关闭输入流 fileOutput.close(); //关闭输出流 } } in.close(); out.close(); System.out.printl
27、n("Disconnected from " + socket.getRemoteSocketAddress()); socket.close(); //关闭套接字 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO
28、 Auto-generated catch block e.printStackTrace(); } } private class HandleInput{ private Map userInfo = new HashMap(); //定义一个map private String username = ""; private String password = "";
29、 public HandleInput(){ userInfo.put("me", "me"); //定义用户名密码 userInfo.put("abc", "abc"); userInfo.put("123", "123"); } public static void main(String[] args) {
30、 try { ServerSocket serverSocket = new ServerSocket(port); //创建一个ServerSocket System.out.println("Server Started"); try { while(true){ Socket theSocket = serverSocket.accept(); //等待连接
31、 try { new SimpleServer(theSocket); } catch (Exception e) { e.printStackTrace(); theSocket.close(); } } } catch (Excep
32、tion e) { // TODO: handle exception e.printStackTrace(); } finally { if(serverSocket != null) serverSocket.close(); //关闭连接 } } catch (IOException e) {
33、 // TODO Auto-generated catch block e.printStackTrace(); } } } 3.3 运行程序 运行程序,要结合服务器端程序,运行服务器端程序,结果如图1-2。 图1-2 服务器程序运行结果 运行客户端程序,得出客户端如图1-3。 图1-3 客户端程序运行结果 客户端对话框输入所要连接的服务器的IP地址,进行客户端和服务器端的连接,连接后,出现如图1-4结果。 图1-4 服务器和客户端连接 接下来,客户端和服务器端
34、进行连接后,可以进行正常的聊天了。其程序执行结果如图1-5所示。 图1-5 服务器和客户端之间的聊天通讯 接下来是在客户端下载服务器上的文件。 图1-6 请求在客户端上下载服务器上的文件 图1-7在客户端登陆上服务器 图1-8 在客户端成功下载服务器上的文件 4结束语 经过两个星期的学习和实践,我也算是顺利的完成了这次课程设计,在实践过程中遇到了很多的困难,感觉自己很难将理论与实践相结合,觉得我们学习的那些知识也派不上用场,通过这次课设,我深刻的认识到实践与理论必须要想结合才能使所学的知识变成可用的,通过自己的努力和老师同学们的帮助,多了
35、一种看待问题的角度;我也发现了我所学知识不扎实,只是走马观花的应付考试,在以后的学习中需要时刻的告诫自己,踏踏实实做好每一步。 本次课程设计是利用java语言编写的,虽说自己以前接触过这种语言,但是经过这两周的学习,我受益匪浅。首先,我进一步弄懂了JAVA语言的编程方法和原则,并学会了编写java程序。其次,使我更深层次的理解到JAVA语言是一种面向对象的语言,具有可视化编程的特点且代码具有可移植等特点。本次课程设计是实现一个UDP即时通讯程序。经过编写程序和运行,调试程序,我对java语言有了更深的了解。另外,使我对UDP协议的特点和工作过程有了更深的了解。UDP协议提供无连接的、不可靠的
36、服务。它工作于传输层,是传输层的重要协议之一。最后,UDP协议是利用客户端和服务器端模型来实现传输的。 本次课程设计使我明白了知识的重要性,同时也更加懂得实践更不可少。我们要经常把所学的知识运用到实践,这样,才能充分的融会贯通。同时,也使我认识到自己动手能力太差,为我以后的学习和发展提供了一个警钟!本次课程设计的过程中,虽然遇到了不少问题,但最后还是成功的完成了。 这次课设对于我而言是有很大的收获,懂得独立寻找资料学习,这是最大的收获,在以后的工作中肯定会面临不懂得问题,有了这次课设的经验,就能够去独立学习并解决困难。 参考文献 [1] AndrewS.Tan
37、enbaum.潘爱民.计算机网络(第四版).清华大学出版社,2004 [2]孙卫琴.JAVA面向对象编程.电子工业出版社,2006 [3] 张立 等.基于Client/Server模式的数据库应用软件的设计与实现.计算机应用研究[J],1999 [4] 俞俊 / 李功 / 汪晓平.Java网络编程.清华大学出版社,2005 [5] 谢希仁.计算机网络(第四版)[M].电子工业出版社,2003 附录1:聊天模块客户端程序设计清单 package com.briup.gui; import jav
38、a.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import .DatagramPacket; import .DatagramSocket; import .InetAddress; public class Client { public static void main(String[] args) { new UDPClient().start(); //调用UDPClient()函数,启动客户端
39、 }} class UDPClient extends Thread { public UDPClient() { } public void run() { //和服务器之间进行连接 System.out.print("请输入所要通讯的服务器的地址:"); String serverip = null; //定义一个数组,用来保存服务器地址,初始化为NULL. //进行异常处理 try { serverip = new BufferedReader(n
40、ew InputStreamReader(System.in)).readLine(); //取得输入的服务器地址 } catch (IOException e1) { //错误处理 e1.printStackTrace(); }finally{ try { DatagramSocket socket = new DatagramSocket(); //建立Socket连接 //实现服务器和客户端程序间的不间断通讯 while (true) { // 发送 System.out.print("客户
41、端发送的消息为:"); //打印消息 String send = new BufferedReader(new InputStreamReader(System.in)).readLine(); //读入客户机输入的消息 byte[] outstr = new byte[send.length()]; //定义一个字节数组,长度为客户端所发送的消息长度 outstr = send.getBytes(); //将得到的客户端消息保存数组中 InetAddress address = InetAddress.ge
42、tByName(serverip); DatagramPacket packet = new DatagramPacket(outstr, outstr.length, address, 80); //向服务器发送数据报 socket.send(packet); //发送数据报 // 接收 byte[] instr = new byte[200]; //定义数组,用来保存接受的数据报 packet = new DatagramPacket(instr, instr.length); //接收数据报 socket
43、receive(packet); //接收数据 String out = new String(packet.getData(),0,packet.getLength()); //取出信息 System.out.println("接受到的服务器消息:" + out); //打印服务器发过来的信息 } } catch (Exception e) { // 错误处理 e.printStackTrace();} }} } 附录2:聊天模块服务器程序设计清单 package com.briup.gui; import java.io
44、BufferedReader; import java.io.InputStreamReader; import .DatagramPacket; import .DatagramSocket; import .InetAddress; public class Server { public static void main(String[] args) { new UDPServer().start(); //启动服务器 } } class UDPServer extends Thread { public UDPServer() { } //缺省构造函数
45、 public void run() { try { DatagramSocket socket = new DatagramSocket(80); //建立一个Socket连接,端口号为80 System.out.println("服务器IP地址为:" + InetAddress.getLocalHost().getHostAddress()); //得到服务器地址,并打印出来 //实现客户端和服务器端的连续通信 while (true) { // 接收 byte[] instr = new byte[200]; //定义
46、数组,用来保存客户端发送来的数据 DatagramPacket receive = new DatagramPacket(instr, instr.length); socket.receive(receive); //接收客户机发过来的数据 String str = new String(receive.getData()); //提取数据 System.out.println("客户端消息:" + str.trim()); //打印客户机消息 // 发送 System.out.print("接收到的服务器消息:"); //
47、打印消息 str = new BufferedReader(new InputStreamReader(System.in)).readLine(); //得到输入的数据 byte[] outstr = new byte[str.length()]; outstr = str.getBytes(); DatagramPacket send = new DatagramPacket(outstr,outstr.length, receive.getAddress(), receive.getPort()); //向客户机发送数据 socket.
48、send(send); //执行发送 } } catch (Exception e) { //错误处理 e.printStackTrace(); } } } 附录3:文件传输模块客户端程序设计清单 import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.File; import java.io.IOException; impor
49、t java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.RandomAccessFile; import .Socket; import .UnknownHostException; public class SimpleClient { private static final int DEFAULT_PORT = 8080; private static final String DEFAULT_HOST = "localhost"; public static void main(String[] args) { String host = DEFAULT_HOST; int port = DEFAULT_PORT; if(args.length > 0){






