importjava.io.*;importjava.net.*;importjava.nio.channels.*;importjava.util.*;importjava.util.regex.*;publicclassPing {staticintDAYTIME_PORT=13;staticintport=DAYTIME_PORT;staticclassTarget {
InetSocketAddress address;
SocketChannel channel;
Exception failure;longconnectStart;longconnectFinish=0;booleanshown=false;
Target(String host) {try{
address=newInetSocketAddress(InetAddress.getByName(host),
port);
}catch(IOException x) {
failure=x;
}
}voidshow() {
String result;if(connectFinish!=0)
result=Long.toString(connectFinish-connectStart)+"ms";elseif(failure!=null)
result=failure.toString();elseresult="Timed out";
System.out.println(address+":"+result);
shown=true;
}
}staticclassPrinterextendsThread {
LinkedList pending=newLinkedList();
Printer() {
setName("Printer");
setDaemon(true);
}voidadd(Target t) {synchronized(pending) {
pending.add(t);
pending.notify();
}
}publicvoidrun() {try{for(;;) {
Target t=null;synchronized(pending) {while(pending.size()==0)
pending.wait();
t=(Target) pending.removeFirst();
}
t.show();
}
}catch(InterruptedException x) {return;
}
}
}staticclassConnectorextendsThread {
Selector sel;
Printer printer;
LinkedList pending=newLinkedList();
Connector(Printer pr)throwsIOException {
printer=pr;
sel=Selector.open();
setName("Connector");
}voidadd(Target t) {
SocketChannel sc=null;try{
sc=SocketChannel.open();
sc.configureBlocking(false);booleanconnected=sc.connect(t.address);
t.channel=sc;
t.connectStart=System.currentTimeMillis();if(connected) {
t.connectFinish=t.connectStart;
sc.close();
printer.add(t);
}else{synchronized(pending) {
pending.add(t);
}
sel.wakeup();
}
}catch(IOException x) {if(sc!=null) {try{
sc.close();
}catch(IOException xx) {
}
}
t.failure=x;
printer.add(t);
}
}voidprocessPendingTargets()throwsIOException {synchronized(pending) {while(pending.size()>0) {
Target t=(Target) pending.removeFirst();try{
t.channel.register(sel, SelectionKey.OP_CONNECT, t);
}catch(IOException x) {
t.channel.close();
t.failure=x;
printer.add(t);
}
}
}
}voidprocessSelectedKeys()throwsIOException {for(Iterator i=sel.selectedKeys().iterator(); i.hasNext();) {
SelectionKey sk=(SelectionKey) i.next();
i.remove();
Target t=(Target) sk.attachment();
SocketChannel sc=(SocketChannel) sk.channel();try{if(sc.finishConnect()) {
sk.cancel();
t.connectFinish=System.currentTimeMillis();
sc.close();
printer.add(t);
}
}catch(IOException x) {
sc.close();
t.failure=x;
printer.add(t);
}
}
}volatilebooleanshutdown=false;voidshutdown() {
shutdown=true;
sel.wakeup();
}publicvoidrun() {for(;;) {try{intn=sel.select();if(n>0)
processSelectedKeys();
processPendingTargets();if(shutdown) {
sel.close();return;
}
}catch(IOException x) {
x.printStackTrace();
}
}
}
}publicstaticvoidmain(String[] args)throwsInterruptedException,
IOException {
args=newString[] {"8888","192.168.10.193"};if(args.length<1) {
System.err.println("Usage: java Ping [port] host...");return;
}intfirstArg=0;if(Pattern.matches("[0-9]+", args[0])) {
port=Integer.parseInt(args[0]);
firstArg=1;
}
Printer printer=newPrinter();
printer.start();
Connector connector=newConnector(printer);
connector.start();
LinkedList targets=newLinkedList();for(inti=firstArg; i
Target t=newTarget(args[i]);
targets.add(t);
connector.add(t);
}
Thread.sleep(2000);
connector.shutdown();
connector.join();for(Iterator i=targets.iterator(); i.hasNext();) {
Target t=(Target) i.next();if(!t.shown)
t.show();
}
}
}