import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class Pinger {
public static class UDPPacket{
int sequence_number;
long timestamp;
}
public static class UDPClient{
int localport,remoteport,packetnum,seqnum,receivenum;
long [] RTTs;
InetAddress Serveraddress;
DatagramSocket datagramSocket = null;
DatagramPacket datagramPacket = null;
public UDPClient(String remotehost, int lp, int rp, int pc)throws Exception{
localport = lp;
remoteport = rp;
packetnum = pc;
seqnum = 0;
receivenum = 0;
RTTs = new long[packetnum + 1];
Serveraddress = InetAddress.getByName(remotehost);
datagramSocket = new DatagramSocket(localport);
}
public void PingerClient(){
try {
for(int i = 1;i <= packetnum;i++) {
UDPPacket send = new UDPPacket();
send.sequence_number = seqnum ++ ;
send.timestamp = System.currentTimeMillis();
byte[] buf = new byte[12];
buf[0] = (byte)((send.timestamp >>> 0)); buf[1] = (byte)((send.timestamp >>> 8));
buf[2] = (byte)((send.timestamp >>> 16)); buf[3] = (byte)((send.timestamp >>> 24));
buf[4] = (byte)((send.timestamp >>> 32)); buf[5] = (byte)((send.timestamp >>> 40));
buf[6] = (byte)((send.timestamp >>> 48)); buf[7] = (byte)((send.timestamp >>> 56));
buf[8] = (byte)((send.sequence_number >>> 0)); buf[9] = (byte)((send.sequence_number >>> 8));
buf[10] = (byte)((send.sequence_number >>> 16)); buf[11] = (byte)((send.sequence_number >>> 24));
datagramPacket = new DatagramPacket(buf, buf.length, Serveraddress, remoteport);
datagramSocket.send(datagramPacket);
Thread t = new Thread(new Respond());
t.start();
Thread.sleep(1000);
}
}catch(Exception e) { e.printStackTrace(); }
long max = 0,min = 1000000,sum = 0;
for(int i = 1;i <= receivenum;i ++) {
if(RTTs[i] > max) max = RTTs[i];
if(RTTs[i] < min) min = RTTs[i];
sum += RTTs[i];
}
System.out.print("sent=" + packetnum + '\t');
System.out.print("receive=" + receivenum + '\t');
System.out.print("lost=" + (double)(packetnum - receivenum) / (double)packetnum + '\t');
System.out.print("rtt min/avg/max = " + min + '/' + (double)sum/(double)receivenum + '/' + max + "ms\n");
}
class Respond implements Runnable {
@Override
public void run() {
try {
UDPPacket receive = new UDPPacket();
byte[] receBuf = new byte[12];
DatagramPacket recePacket = new DatagramPacket(receBuf, receBuf.length);
datagramSocket.receive(recePacket);
long cur = System.currentTimeMillis();
receive.sequence_number = (int)receBuf[8]; receive.sequence_number += (int)receBuf[9] << 8;
receive.sequence_number += (int)receBuf[10]<< 16; receive.sequence_number += (int)receBuf[11]<< 32;
receive.timestamp = (long)receBuf[0]; receive.timestamp += (long)receBuf[1] << 8;
receive.timestamp += (long)receBuf[2] << 16; receive.timestamp += (long)receBuf[3] << 24;
receive.timestamp += (long)receBuf[4] << 32; receive.timestamp += (long)receBuf[5] << 40;
receive.timestamp += (long)receBuf[6] << 48; receive.timestamp += (long)receBuf[7] << 56;
RTTs[++receivenum] = cur - receive.timestamp;
System.out.print("size = " + recePacket.getLength() + '\t');
System.out.print("from = " + recePacket.getAddress() + '\t');
System.out.print("seq = " + receive.sequence_number + '\t');
System.out.print("rtt = " + RTTs[receivenum] + "ms\n");
}
catch (SocketException e) {e.printStackTrace();}
catch (UnknownHostException e) {e.printStackTrace();}
catch (IOException e) {e.printStackTrace();}
//finally {if(datagramSocket != null) datagramSocket.close();}
}
}
}
public static class UDPServer{
int localport;
DatagramSocket datagramSocket = null;
DatagramPacket datagramPacket = null;
public UDPServer(int lp) throws Exception{
localport = lp;
System.out.println("serving...");
datagramSocket = new DatagramSocket(localport);
}
public void PingerServer() throws Exception {
while(true) {
byte[] receBuf = new byte[12];
datagramPacket = new DatagramPacket(receBuf, receBuf.length);
datagramSocket.receive(datagramPacket);
Thread t = new Thread(new Respond(datagramPacket,receBuf));
t.start();
}
}
class Respond implements Runnable {
DatagramPacket packet = null;
byte[] info;
Respond(DatagramPacket p,byte[] b){
packet = p;
info = b;
}
public void run(){
try {
UDPPacket receive = new UDPPacket();
long time = System.currentTimeMillis();
receive.sequence_number = (int)info[8]; receive.sequence_number += (int)info[9] << 8;
receive.sequence_number += (int)info[10]<< 16; receive.sequence_number += (int)info[11]<< 24;
receive.timestamp = (long)info[0]; receive.timestamp += (long)info[1] << 8;
receive.timestamp += (long)info[2] << 16; receive.timestamp += (long)info[3] << 24;
receive.timestamp += (long)info[4] << 32; receive.timestamp += (long)info[5] << 40;
receive.timestamp += (long)info[6] << 48; receive.timestamp += (long)info[7] << 56;
System.out.print("time = " + time + '\t');
System.out.print("from = " + packet.getAddress() + '\t');
System.out.print("seq = " + receive.sequence_number + '\n');
DatagramPacket recePacket = new DatagramPacket(info,info.length,packet.getAddress(),packet.getPort());
datagramSocket.send(recePacket);
}
catch (SocketException e) {e.printStackTrace();}
catch (IOException e) {e.printStackTrace();}
//finally {if(datagramSocket != null) datagramSocket.close();}
}
}
}
public static void main(String []args){
boolean mode;//1 is Server mode and 0 is Client mode
if( (args.length >= 2) && (args[0].equals("-l")) ) {
if( (args.length == 2) ) mode = true;
else if ((args.length == 8) && (args[2].equals("-h")) && (args[4].equals("-r")) && (args[6].equals("-c")))
mode = false;
else {
System.out.println("Error: wrong arguments");
return;
}
}
else {
System.out.println("Error: missing or additional arguments");
return;
}
if(mode) {
System.out.println("Server mode.");
UDPServer server = null;
try {server = new UDPServer(Integer.parseInt(args[1]));}
catch (NumberFormatException e1) {e1.printStackTrace();}
catch (Exception e1) {e1.printStackTrace();}
try {server.PingerServer();}
catch (Exception e) {e.printStackTrace();}
}
else {
System.out.println("Client mode.");
UDPClient client = null;
try {client = new UDPClient(args[3],Integer.parseInt(args[1]),Integer.parseInt(args[5]),Integer.parseInt(args[7]));}
catch (NumberFormatException e) {e.printStackTrace();}
catch (Exception e) {e.printStackTrace();}
client.PingerClient();
}
}
}