import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
*
* @author isWudn
*
* *******************************服务器端******************************
* 1、可以并发地为多个用户服务
* 2、显示用户通过客户端发送来的消息内容(包含头部和payload)
* 3、能够模拟分组的丢失、能够模拟分组传输延迟
* 4、将用户发送来的请求request在延迟一段随机选择的时间(小于1s)后返回给客户端,作为收到请求的响应reply
* 5、通过如下命令行启动服务器:java PingServer port。port为PingServer的工作端口号
*
*/
public class PingServer{
private int initPort;//监听的端口号
private DatagramSocket socket;//服务器的socket
private DatagramPacket packet;//从客户端收到的packet
private byte[] buf = new byte[1024];
/**
* 构造器
* @param initPort服务器监听的端口号
*/
public PingServer(int initPort) {
this.initPort = initPort;
}
/**
* 线程体
*/
public void run() {
System.out.println("编程实现基于UDP的PING (Java)服务器端");
System.out.println("----------PING SERVER STARTED---------");
try {
//初始化socket,定义socket的端口号
socket = new DatagramSocket(initPort);
} catch (SocketException e) {
//捕获到此异常一般是输入端口非法 或者 被占用
System.out.println("Listening port" + initPort + "fail!");
e.printStackTrace();
//初始化端口号失败,终止程序
System.exit(0);
}
//死循环,不断监听是否有报文请求
while(true) {
//获取客户端发来的报文
packet = new DatagramPacket(buf,buf.length);
try {
//程序会停留在该语句,直到有新的请求连接产生
socket.receive(packet);
} catch (IOException e) {
System.out.println("Request receive exception!");
e.printStackTrace();
}
//启动线程
ThreadServer server = new ThreadServer(socket,packet);
server.start();
}
}
public void destroy() {
socket.close();//回收资源
}
public static void main(String[] args) {
//初始化服务器
PingServer ping = new PingServer(Integer.valueOf(args[0]));
//PingServer ping = new PingServer(9999);
ping.run();
}
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
*
* @author isWudn
*
* *****************PingServer用来处理多用户请求的线程***********************
* 2、显示用户通过客户端发送来的消息内容(包含头部和payload)
* 3、能够模拟分组的丢失、能够模拟分组传输延迟
* 4、将用户发送来的请求request在延迟一段随机选择的时间(小于1s)后返回给客户端,作为收到请求的响应reply
*
*/
public class ThreadServer extends Thread{
private DatagramSocket socket;//接收和发送数据报
private DatagramPacket packet;//数据报
/**
* 构造器
* @param socket服务器的socket
* @param packet客户端发送过来的packet
*/
public ThreadServer(DatagramSocket socket, DatagramPacket packet) {
//初始化socket和packet
this.socket = socket;
this.packet = packet;
}
public void run() {
//定义延迟回送报文的随机时间,范围在0~1500之间,要比1000大才能延迟
long randomTime = (long)(Math.random()*1500);
/***********************接收报文****************************/
String data = null;
//如果随机时间大于1400,则认为分组丢失
if(randomTime>1400) {
data = "Receive message lost!";
System.out.println(data);
}else {
//获取packet对象里封装的字符数组
data = new String(packet.getData());
System.out.println("Receiving a message:" + data);
}
/************************发送报文********************************/
byte[] buffer = data.getBytes();
//获取客户端地址
InetAddress host = packet.getAddress();
//获取客户端应用进程端口号
int port = packet.getPort();
//回送给客户端的报文
DatagramPacket sendPacket = new DatagramPacket(buffer,buffer.length,host,port);
//休眠0~1.5秒,模拟传输延迟
try {
sleep(randomTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
socket.send(sendPacket);
} catch (IOException e) {
System.out.println("The server failed to send a reply message!");
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*
* @author isWudn
*
* ****************************客户端***********************************
* 1、启动后发送10个request。每发送一个request后,最多等待1秒便接收PingServer返回的reply消息。
* 如果在该时间内没有收到服务器的reply,则认为该请求或对该请求的reply已经丢失;
* 在收到reply后立即发送下一个request。
*
* 2、请求消息的payload中至少包含关键字PingUDP、序号、时间戳等内容。
* 如:PingUDP SequenceNumber TimeStamp CRLF
* 其中:CRLF表示回车换行符(0X0D0A);TimeStamp为发送该消息的机器时间。
*
* 3、为每个请求计算折返时间(RTT),统计10个请求的平均RTT、最大/小RTT。
*
* 4、通过如下命令行启动:java PingClient host port。
* host为PingServer所在的主机地址;port为PingServer的工作端口号
*
*/
public class PingClient extends Thread{
//客户端socket
private DatagramSocket client;
//服务器的IP地址
private InetAddress hostAddress;
//服务器的应用进程端口号
private int port;
//定义并初始化接收到的响应报文的个数
private int replyNum = 0;
//定义并初始化最小往返时间、最大往返时间、平均往返时间
private long minRtt = 0, maxRtt = 0, averRtt = 0,sumRtt = 0;
//每一个请求对应的rtt,默认初始化为0
private long[] rtt = new long[10];
/**
* 构造器
* @param host服务器地址
* @param port服务器端口
*/
public PingClient(String host, int port) {
//有效端口的范围是0~65535
if(port < 0 || port > 65535) {
System.out.println("Invalid port number!");
//如果端口号违法,终止程序
System.exit(0);
}
this.port = port;
try {
//初始化客户端实例,将该实例绑定到本机默认的IP地址,本机所有可用端口中随机选择的某个端口
client = new DatagramSocket();
//根据服务器主机名称确定服务器的IP地址
hostAddress = InetAddress.getByName(host);
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
System.out.println("Invalid host name!");
e.printStackTrace();
}
}
/**
* 线程体
*/
public void run() {
//定义时间戳格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-ddhh:mm:ss.SS");
System.out.println("Pinging " + hostAddress + ":");
//模拟发送10条请求
for(int i=0; i<10; i++) {
//数据包装顺序:字符串-->字节数组-->packet报文
/************************生成发送报文***************************/
//发送报文前的时间
Date sendTime = new Date();
//请求数据
String outMessage = "head:request " + i +"\n"
+ "payload:PingUDP SequenceNUmber:" + i
+ " TimeStamp:" + sdf.format(sendTime);
//将请求数据放进缓冲区内
byte[] buffer = outMessage.getBytes();
//生成发送报文实例
DatagramPacket sendPacket = new DatagramPacket(buffer,buffer.length,hostAddress,port);
/*************************生成接收报文******************************/
byte[] buf = new byte[buffer.length];
DatagramPacket recievePacket = new DatagramPacket(buf,buf.length);
/*****************************************************************/
//接收到的响应信息
String recieve = null;
try {
//发送到服务器端
client.send(sendPacket);
//接收响应报文
//client.setSoTimeout(1000);//设置超时时间为1秒
client.receive(recievePacket);
recieve = new String(recievePacket.getData());
//记录接收后的时间
Date recieveTime = new Date();
//计算往返时间
rtt[i] = recieveTime.getTime()-sendTime.getTime();
} catch (IOException e) {
e.printStackTrace();
}
//如果接收时间大于1000ms,则认为请求丢失或者对请求的回复丢失
if(rtt[i]>1000) {
recieve = "head:request "+ i +"\n"
+ "Response message lost or Request timed out!";
}else {
recieve = recieve + "\n" + "rtt:" + rtt[i] +"ms";
}
System.out.println(recieve);
}
minRtt = rtt[0];
for(int i=0;i<10;i++) {
if(rtt[i] > 1000) continue;//请求失败不计算往返时间
replyNum++;
//计算最小往返时间
if(minRtt > rtt[i]) {
minRtt = rtt[i];
}
//计算最大往返时间
if(maxRtt < rtt[i]) {
maxRtt = rtt[i];
}
//计算总往返时间
sumRtt += rtt[i];
}
if(replyNum!=0) {
//计算平均往返时间
averRtt = sumRtt/replyNum;
System.out.println("Ping statistics for " + hostAddress + ":");
System.out.println(" Packets: Sent=10, Received=" + replyNum +", Lost=" + (10-replyNum));
System.out.println("Approximate round trip times in milli-seconds:");
System.out.println(" minRTT:" + minRtt + "ms, maxRTT:" + maxRtt + "ms, averRTT:" + averRtt + "ms");
}else {
System.out.println("Failed to send request! Unable to return message!");
}
//关闭线程
client.close();
}
public static void main(String[] args) {
PingClient clientThread = new PingClient(args[0], Integer.valueOf(args[1]));
//PingClient clientThread = new PingClient("127.0.0.1", 9999);
clientThread.start();
}
}
cmd错误:找不到或无法加载主类 和 错误:找不到符号