原理:
采用UDP协议来实现ICMP协议中的Ping报文功能,就必须在应用层来模拟网格层中的Ping报文的工作流程,即首先由客户机向服务器段发送一个应用层的UDP Ping请求报文,在服务器段程序接收到UDP Ping请求报文后,就会向客户机返回一个UDP Ping响应报文。客户机通过判断程序中收到的报文及其相关的信息可以判断链路状况。
流程图:
编写服务器段程序
功能:
1.根据用户输入参数打开特定的插口,并对插口进行监听,
2.接受从客户机发送过来的应用层Ping请求报文并打印
3.向客户机回复Ping响应报文
import java.io.*;
import java.net.*;
import java.nio.channels.NonWritableChannelException;
import java.util.*;
public class PingServer {
private static final double LOSS_RATE=0.3;
private static final int AVERAGE_DELAY=100;
public static void main(String[] args)throws Exception {
if(args.length!=1) {
System.out.println("Required arguments:port");
return;
}
int port = Integer.parseInt(args[0]);
Random random = new Random();
DatagramSocket socket = new DatagramSocket(port);
while(true) {
DatagramPacket requset=new DatagramPacket(new byte[1024], 1024);
socket.receive(requset);
printData(requset);
if(random.nextDouble()<LOSS_RATE) {
System.out.println("Reply not sent");
continue;
}
Thread.sleep((int)(random.nextDouble()*2*AVERAGE_DELAY));
InetAddress clientHost=requset.getAddress();
int clientPort = requset.getPort();
byte[] buf = requset.getData();
DatagramPacket reply= new DatagramPacket(buf, buf.length,clientHost,clientPort);
socket.send(reply);
System.out.println("Reply sent");
}
}
private static void printData(DatagramPacket requset) throws Exception {
// TODO Auto-generated method stub
byte[] buf = requset.getData();
ByteArrayInputStream bais=new ByteArrayInputStream(buf);
InputStreamReader isr= new InputStreamReader(bais);
BufferedReader br=new BufferedReader(isr);
String line = br.readLine();
System.out.println("Received from"+ requset.getAddress().getHostAddress()+"."+new String(line));
}
}
编写客户机程序
功能
1.与服务器建立连接构建UDP Ping请求报文
2.将请求报文发送给服务器 同时等待和接收服务器发回的响应报文,连续发10次Ping命令后关闭插口
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
public class PingClient {
public static void main(String[] args)throws Exception {
if(args.length==0) {
System.out.println("Required argument:Host port");
return;
}
if(args.length==1) {
System.out.println("Required argument: port");
return;
}
String host=args[0].toString();
int port = Integer.parseInt(args[1]);
DatagramSocket clientSocket = new DatagramSocket();
clientSocket.setSoTimeout(1000);
InetAddress IPAddress=InetAddress.getByName(host);
long sendTime,receiveTime;
for(int i=0;i<10;i++) {
byte[] sendData=new byte[1024];
byte[] receviceData=new byte[1024];
Date currentTime=new Date();
SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String timeStamp= formatter.format(currentTime);
String pingMessage= "Ping"+"i"+""+timeStamp+""+"\r\n";
sendData = pingMessage.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,IPAddress,port);
try {
sendTime = System.currentTimeMillis();
clientSocket.send(sendPacket);
DatagramPacket receivePacket = new DatagramPacket(receviceData, receviceData.length);
clientSocket.receive(receivePacket);
receiveTime =System.currentTimeMillis();
long latency= receiveTime-sendTime;
String serverAddress= receivePacket.getAddress().getHostAddress();
System.out.println("From"+serverAddress + ":"+latency+"ms.");
}catch(java.net.SocketTimeoutException ex){
String reply="No reply";
System.out.println(reply);
}
}
clientSocket.close();
}
}
效果复现:
找到对应java文件的编译文件,进入PowerShell使用CMD命令执行对应语句:
首先开发一个端口号80
然后再开一个PowerShell窗口执行ServerClient.java 127.0.0.1 80
此时服务器部分:
大功告成!!!!!!