广工计算机网络课设基于UDP的ping.docx
《广工计算机网络课设基于UDP的ping.docx》由会员分享,可在线阅读,更多相关《广工计算机网络课设基于UDP的ping.docx(26页珍藏版)》请在冰豆网上搜索。
广工计算机网络课设基于UDP的ping
《计算机网络》课程设计
学院____计算机学院_______
专业______软件工程_______
年级班别______12级4班_______
学号3112006291
学生姓名______林炳城______
指导教师____梁路________
成绩
计算机网络课程设计任务书
设计题目
编程实现基于UDP的PING(Java)
已知技术参数和设计要求
1.编程实现PING的服务器端和客户端,实现操作系统提供的ping命令的类似功能。
2.服务器端PingServer功能:
2.1可以2.2显示用户通过客户端发送来的消息内容(包含头部和payload);
2.3能够模拟分组的丢失;能够模拟分组传输延迟;
2.4将用户发送来的请求request在延迟一段随机选择的时间(小于1s)后返回给客户端,作为收到请求的响应reply;
2.5通过如下命令行启动服务器:
javaPingServerport。
port为PingServer的工作端口号
3.客户端PingClient功能:
3.1启动后发送10个request。
发送一个request后,最多等待1秒以便接收PingServer返回的reply消息。
如果在该时间内没有收到服务器的reply,则认为该请求或对该请求的reply已经丢失;在收到reply后立即发送下一个request。
3.2请求消息的payload中至少包含关键字PingUDP、序号、时间戳等内容。
如:
PingUDPSequenceNumberTimeStampCRLF
其中:
CRLF表示回车换行符(0X0D0A);TimeStamp为发送该消息的机器时间。
3.3为每个请求计算折返时间(RTT),统计10个请求的平均RTT、最大/小RTT。
3.4通过如下命令行启动:
javaPingClienthostport。
host为PingServer所在的主机地址;port为PingServer的工作端口号
设计内容与步骤
1.学习ICMP,了解ping命令的工作机理;
2.学习JavaUDPSocket通信机制;
3.了解Java多线程程序设计;
4.服务器PingServer程序设计;
5.客户端PingClient程序设计。
6.调试与演示
设计工作计划与进度安排
1.ping命令工作机制学习2小时
2.JavaUDPSocket通信机制2小时
3.Java多线程程序设计4小时
4.PingServer程序设计6小时
5.PingClient程序设计12小时
6.调试与演示4小时
6.课程设计说明书10小时
一、设计环境
操作系统:
win8
开发环境:
JDK1.7
IDE:
eclipse
二、课程设计的目的
本次课程设计的目的在掌握计算机网络理论的基础上,了解网络技术,掌握计算机网络相关设计方法和思想,希望能通过本次的课程设计,达到巩固和综合应用计算机网络原理和知识,本次课程设计主要是编程实现基于UDP的ping,使用java语言编程,编写一个实验程序、仿真模拟Ping命令,通过观察实验结果,从而判定本次程序设计是否成功完成任务。
三、理论基础
3.1UDP简介
UDP是UserDatagramProtocol的简称,中文名是用户数据包协议,是OSI(OpenSystemInterconnection,开放式系统互联)参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETFRFC768是UDP的正式规范。
UDP在IP报文的协议号是17。
UDP协议全称是用户数据报协议[1],在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。
在OSI模型中,在第四层——传输层,处于IP协议的上一层。
UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。
UDP用来支持那些需要在计算机之间传输数据的网络应用。
包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。
UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天UDP仍然不失为一项非常实用和可行的网络传输层协议。
与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。
根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。
UDP协议的主要作用是将网络数据流量压缩成数据包的形式。
一个典型的数据包就是一个二进制数据的传输单位。
每一个数据包的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。
3.2ping简介
Ping是Windows下的一个命令在Unix和Linux下也有这个命令。
ping也属于一个通信协议,是TCP/IP协议的一部分。
利用“ping”命令可以检查网络是否连通,可以很好地帮助我们分析和判定网络故障。
应用格式:
Ping空格IP地址。
该命令还可以加许多参数使用,具体是键入Ping按回车即可看到详细说明。
PING(PacketInternetGroper),因特网包探索器,用于测试网络连接量的程序。
Ping发送一个ICMP(InternetControlMessagesProtocol)即因特网信报控制协议;回声请求消息给目的地并报告是否收到所希望的ICMPecho(ICMP回声应答)。
它是用来检查网络是否通畅或者网络连接速度的命令。
作为一个生活在网络上的管理员或者黑客来说,ping命令是第一个必须掌握的DOS命令,它所利用的原理是这样的:
利用网络上机器IP地址的唯一性,给目标IP地址发送一个数据包,再要求对方返回一个同样大小的数据包来确定两台网络机器是否连接相通,时延是多少。
ping指的是端对端连通,通常用来作为可用性的检查,但是某些病毒木马会强行大量远程执行ping命令抢占你的网络资源,导致系统变慢,网速变慢。
严禁ping入侵作为大多数防火墙的一个基本功能提供给用户进行选择。
通常的情况下你如果不用作服务器或者进行网络测试,可以放心的选中它,保护你的电脑。
四、基本要求
4.1编程实现PING的服务器端和客户端,实现操作系统提供的ping命令的类似功能。
4.2服务器端PingServer功能:
4.2.1可以2.2显示用户通过客户端发送来的消息内容(包含头部和payload);
4.2.3能够模拟分组的丢失;能够模拟分组传输延迟;
4.2.4将用户发送来的请求request在延迟一段随机选择的时间(小于1s)后返回给客户端作为收到请求的响应reply;
4.2.5通过如下命令行启动服务器:
javaPingServerport。
port为PingServer的工作端口号
4.3客户端PingClient功能:
4.3.1启动后发送10个request。
发送一个request后,最多等待1秒以便接收PingServer返回的reply消息。
如果在该时间内没有收到服务器的reply,则认为该请求或对该请求的reply已经丢失;在收到reply后立即发送下一个request。
4.3.2请求消息的payload中至少包含关键字PingUDP、序号、时间戳等内容。
如:
PingUDPSequenceNumberTimeStampCRLF其中:
CRLF表示回车换行符(0X0D0A);TimeStamp为发送该消息的机器时间。
4.3.3为每个请求计算折返时间(RTT),统计10个请求的平均RTT、最大/小RTT。
4.3.4通过如下命令行启动:
javaPingClienthostport。
host为PingServer所在的主机地址
port为PingServer的工作端口号
五、设计思想
UDP协议的全称是用户数据报,在网络中它与TCP协议一样用于处理数据包,在OSI模型中,在第四层----传输层,处于IP协议的上一层,UDP有不提供数据报分组、组装和不能对数据包的排序的缺点,也就是说,当报文发送之后,是无法得知是否安全完整的到达目的地。
这个课设通过调用javaJDK中包下的DatagramSocket和DatagramPacket类,可以实现对用户数据报文的控制,DatagramSocket类用于创建接收和发送UDP的Spcket实例,调用DatagramPacket类用于处理报文,因为它可以将Byte数组、目标地址、目标端口等数据包装成报文或者将报文拆卸成Byte数组。
通过调用DatagramSocket和DatagramPacket类来实现操作系统提供的ping命令的类似功能。
编程实现基于UDP的ping的思想可以概括为几点:
5.1服务器端PingServer功能:
5.1.1可以并发地为多个用户服务;
5.1.2显示用户通过客户端发送来的消息内容(包含头部和payload);
5.1.3将用户发送来的请求在延迟一段时间后返回给客户端,作为收到请求的相应。
5.1.4通过javaPingServer9999(端口号可以任意选择)命令行来启动服务器。
5.2客户端PingClient功能:
5.2.1启动都发送10个请求,发送一个请求后,最多等待1秒以便接收PingServer返回的响应消息。
5.2.2请求消息的payload中包含有关键字PingUDP、序号、时间戳等内容。
5.2.3为每个请求计算折返时间(RTT),统计10个请求的平均RTT、min/max的RTT。
5.2.4通过javaPingClientlocalhost(本机IP地址)9999命令行启动。
5.3程序设计流程图
根据课程设计的要求,结合程序设计流程,本次设计按如下的流程进行
六、源程序
6.1服务器端代码
importjava.io.IOException;
import.DatagramPacket;
import.DatagramSocket;
import.InetAddress;
import.SocketException;
//importjava.util.Scanner;
/**
*服务器端
*@authorLinBingcheng
*/
publicclassPingServerextendsThread{
privateintinitPort;//监听的端口号
privateDatagramSocketserverSocket;//数据包套接字
privateDatagramPacketreceivePacket;//接受到的数据分组
privatebyte[]buffer=newbyte[1024];//数据包使用的缓冲区
publicPingServer(intinitPort){
this.initPort=initPort;
}
publicvoidrun(){
System.out.println("编程实现基于UDP的PING(Java)服务端");
System.out.println("-------PINGSERVERSTARTED-------");
//System.out.print("请输入监听的端口号:
");
//Scannerscanner=newScanner(System.in);//
//接收从系统指定输入方式输入的数据(默认System.in为键盘)
//intinitPort=scanner.nextInt();//获取端口port
try{
//根据输入的监听端口生成server端DatagramSocket实例
serverSocket=newDatagramSocket(initPort);
}catch(SocketExceptione1){
//捕获到此异常一般是输入的端口非法,或者被占用
System.out.println("监听端口"+initPort
+"失败,端口非法或已被占用,请重新启动输入其他有效空闲端口");
e1.printStackTrace();
System.exit(0);//中止程序
}
//死循环,不断的监听是否有请求数据
while(true){
receivePacket=newDatagramPacket(buffer,buffer.length);//生成接收数据报包实例
//监听是否有用户发出新的request连接到PingServer
//程序会陷入到该语句,知道有新的连接产生
try{
serverSocket.receive(receivePacket);
}catch(IOExceptione){
System.out.println("分组接受异常");
e.printStackTrace();
}
ServerThreadthread=newServerThread(serverSocket,receivePacket);//到此步说明有新的请求了,此时生成一个新的服务线程
thread.start();//启动线程
}
}
@Override
publicvoiddestroy(){
serverSocket.close();//回收资源
}
publicstaticvoidmain(String[]args)throwsException{
PingServerpingServer=newPingServer(Integer.valueOf(args[0]));//初始化服务器
pingServer.start();
}
}
/**
*PingServer处理多用户请求的对各个线程的
*@authorLinBingcheng
*/
classServerThreadextendsThread{
privateDatagramPacketreceivePacket;//接受到的数据分组
privateDatagramSocketserverSocket;//数据包套接字
publicServerThread(DatagramSocketserverSocket,
DatagramPacketreceivePacket){
this.receivePacket=receivePacket;
this.serverSocket=serverSocket;
}
@Override
publicvoidrun(){
byte[]buffer=newbyte[4096];//数据使用的缓冲区
longrandomTime=(long)(Math.random()*2000);//到此步说明接收到新连接,在此生成随机数,模拟传输延迟
Stringsentence=null;//接收到的数据
try{
sleep(randomTime);//休眠睡眠,用于模拟传输延迟
}catch(InterruptedExceptione){
e.printStackTrace();
}
if(randomTime>1000){//如果随机数大于1000,模拟数据包丢失
sentence="datalose\n";//数据丢失的信息
}else{
sentence=(newString(receivePacket.getData())).substring(0,100);//将数据从缓冲区轮换成字符串
}
InetAddresshost=receivePacket.getAddress();//获取客户端的ip地址
intport=receivePacket.getPort();//获取客户端的通讯端口
buffer=sentence.getBytes();//请求数据转换成byte数组,用于发回客户端
DatagramPacketsendPacket=newDatagramPacket(buffer,buffer.length,
host,port);//生成数据包,已经保存好发送目的地的地址和端口了
try{
serverSocket.send(sendPacket);//发送数据给客户端
}catch(Exceptione){
e.printStackTrace();
}
System.out.println(sentence);//显示请求结果
}
publicDatagramPacketgetReceivePacket(){
returnreceivePacket;
}
publicvoidsetReceivePacket(DatagramPacketreceivePacket){
this.receivePacket=receivePacket;
}
publicDatagramSocketgetServerSocket(){
returnserverSocket;
}
publicvoidsetServerSocket(DatagramSocketserverSocket){
this.serverSocket=serverSocket;
}
}
6.2客户端代码
importjava.io.IOException;
import.DatagramPacket;
import.DatagramSocket;
import.InetAddress;
importjava.text.SimpleDateFormat;
importjava.util.Date;
//importjava.util.Scanner;
/**
*客户端
*@authorLinBingcheng
*/
publicclassPingClient{
publicstaticvoidmain(String[]args)throwsException{
//Scannerscanner=newScanner(System.in);//接收从系统指定输入方式输入的数据(默认System.in为键盘)
Stringhost=args[0];//scanner.nextLine();//获取服务器端所在的主机地址
intport=Integer.valueOf(args[1]);//scanner.nextInt();//获取服务器端监听的端口号
Long[]rtt=newLong[10];//用于存储rtt,用于最后的统计
for(inti=1;i<=10;i++){//模拟发送10条请求
SimpleDateFormatsdf=newSimpleDateFormat(
"yyyy-MM-ddhh:
mm:
ss.SS");//时间戳格式
DatesendBefore=newDate();//记录发送前时间
Stringsentence="head:
request"+i
+"\n"//模拟用的请求数据
+"playload:
PingUDPSequenceNumber:
"+i+"TimeStamp:
"
+sdf.format(sendBefore)+"\n";
DatagramSocketclientSocket=newDatagramSocket();//生成客户端DatagramSocket实例
InetAddressIPAddress=InetAddress.getByName(host);//生成ip地址实例
byte[]buffer=newbyte[1024];//数据包使用的缓冲区
buffer=sentence.getBytes();//将请求数据放进缓冲区内
DatagramPacketsendPacket=newDatagramPacket(buffer,
buffer.length,IPAddress,port);//生成发送数据包实例
clientSocket.send(sendPacket);//发送到服务器端
DatagramPacketreceivePacket=newDatagramPacket(buffer,buffer.length);//生成接收数据包实例
try{//接收从服务端返回的数据包
clientSocket.receive(receivePacket);
}catch(IOExceptione){
System.out.println("分组接受异常");
e.printStackTrace();
}
StringreceiveSentence=newString(receivePacket.getData());//将数据从缓冲区轮换成字符串
DatereceiveAfter=newDate();//记录接收后的时间
rtt[i-1]=receiveAfter.getTime()-sendBefore.getTime();//计算rtt
if(rtt[i-1]>1000){//如果接收时间大约1000ms,视为数据包丢失
rtt[i-1]=(long)1000;
receiveSentence="datalose\n";
}
System.out.println(receiveSentence);//显示从server返回的数