/* * Java Network Programming, Second Edition * Merlin Hughes, Michael Shoffner, Derek Hamner * Manning Publications Company; ISBN 188477749X * * http://nitric.com/jnp/ * * Copyright (c) 1997-1999 Merlin Hughes, Michael Shoffner, Derek Hamner; * all rights reserved; see license.txt for details. */ import java.io.*; import java.net.*; public class Ping { static final int DEFAULT_PORT = 7; static final int UDP_HEADER = 20 + 8; static final int BACKSPACE = 8; public static void main (String[] args) throws IOException { parseArgs (args); init (); for (int i = 0; (i < count) || (count == 0); ++ i) { long past = System.currentTimeMillis (); ping (i, past); try { pong (i, past); } catch (InterruptedIOException ignored) { } } socket.close (); printStats (); } static String host = null; static int port, count = 32, delay = 1000, size = 64; static boolean flood = false; static void parseArgs (String args[]) { for (int i = 0; i < args.length; ++ i) { if (args[i].startsWith ("-")) { if (args[i].equals ("-c") && (i < args.length - 1)) count = Integer.parseInt (args[++ i]); else if (args[i].equals ("-n") && (i < args.length - 1)) count = Integer.parseInt (args[++ i]); else if (args[i].equals ("-i") && (i < args.length - 1)) delay = Math.max (10, Integer.parseInt (args[++ i])); else if (args[i].equals ("-s") && (i < args.length - 1)) size = Integer.parseInt (args[++ i]); else if (args[i].equals ("-l") && (i < args.length - 1)) size = Integer.parseInt (args[++ i]); else if (args[i].equals ("-f")) flood = true; else syntaxError (); } else { if (host != null) syntaxError (); int colon = args[i].indexOf (":"); host = (colon > -1) ? args[i].substring (0, colon) : args[i]; port = ((colon > -1) && (colon < args[i].length () - 1)) ? Integer.parseInt (args[i].substring (colon + 1)) : DEFAULT_PORT; } } if (host == null) syntaxError (); } static void syntaxError () { throw new IllegalArgumentException ("\nPing [-c count] [-i wait] [-s packetsize] [-f] [:]\nOR\nPing [-n count] [-i wait] [-l packetsize] [-f] [:]"); } static DatagramSocket socket; static byte[] outBuffer, inBuffer; static DatagramPacket outPacket, inPacket; static void init () throws IOException { socket = new DatagramSocket (); outBuffer = new byte[Math.max (12, size - UDP_HEADER)]; outPacket = new DatagramPacket (outBuffer, outBuffer.length, InetAddress.getByName (host), port); inBuffer = new byte[outBuffer.length]; inPacket = new DatagramPacket (inBuffer, inBuffer.length); } static int sent = 0; static void ping (int seq, long past) throws IOException { writeInt (seq, outBuffer, 0); writeLong (past, outBuffer, 4); socket.send (outPacket); ++ sent; if (flood) { System.out.write ('.'); System.out.flush (); } } static final void writeInt (int datum, byte[] dst, int offset) { dst[offset] = (byte) (datum >> 24); dst[offset + 1] = (byte) (datum >> 16); dst[offset + 2] = (byte) (datum >> 8); dst[offset + 3] = (byte) datum; } static final void writeLong (long datum, byte[] dst, int offset) { writeInt ((int) (datum >> 32), dst, offset); writeInt ((int) datum, dst, offset + 4); } static int received = 0; static void pong (int seq, long past) throws IOException { long present = System.currentTimeMillis (); int tmpRTT = (maxRTT == 0) ? 500 : (int) maxRTT * 2; int wait = Math.max (delay, (seq == count - 1) ? tmpRTT : 0); do { socket.setSoTimeout (Math.max (1, wait - (int) (present - past))); socket.receive (inPacket); ++ received; present = System.currentTimeMillis (); processPong (present); } while ((present - past < wait) && !flood); } static long minRTT = 100000, maxRTT = 0, totRTT = 0; static void processPong (long present) { int seq = readInt (inBuffer, 0); long when = readLong (inBuffer, 4); long rtt = present - when; if (!flood) { System.out.println ((inPacket.getLength () + UDP_HEADER) + " bytes from " + inPacket.getAddress ().getHostName () + ": seq no " + seq + " time=" + rtt + " ms"); } else { System.out.write (BACKSPACE); System.out.flush (); } if (rtt < minRTT) minRTT = rtt; if (rtt > maxRTT) maxRTT = rtt; totRTT += rtt; } static final int readInt (byte[] src, int offset) { return (src[offset] << 24) | ((src[offset + 1] & 0xff) << 16) | ((src[offset + 2] & 0xff) << 8) | (src[offset + 3] & 0xff); } static final long readLong (byte[] src, int offset) { return ((long) readInt (src, offset) << 32) | ((long) readInt (src, offset + 4) & 0xffffffffL); } static void printStats () { System.out.println (sent + " packets transmitted, " + received + " packets received, " + (100 * (sent - received) / sent) + "% packet loss"); if (received > 0) System.out.println ("round-trip min/avg/max = " + minRTT + '/' + ((float) totRTT / received) + '/' + maxRTT + " ms"); } }