/* * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.tools.visualvm.host.impl; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; public class Ping { // The default daytime port static int RMIREGISTRY_PORT = 1099; // The port we'll actually use int port = RMIREGISTRY_PORT; List<InetAddress> foundHosts; // Representation of a ping target // class Target { InetSocketAddress address; SocketChannel channel; boolean failure; long connectStart; long connectFinish = 0; Boolean status; Target(InetAddress host,int port) { address = new InetSocketAddress(host,port); } private void done() { status = Boolean.valueOf(connectFinish != 0); if (status.booleanValue()) { foundHosts.add(address.getAddress()); } } private void status() { if (status == null) { System.out.println("Status: "+address.getAddress().getHostAddress()+" no status"); } else { System.out.println("Status: "+address.getHostName()+" "+status); } } } // Thread for printing targets as they're heard from // // Thread for connecting to all targets in parallel via a single selector // static class Connector extends Thread { Selector sel; // List of pending targets. We use this list because if we try to // register a channel with the selector while the connector thread is // blocked in the selector then we will block. // LinkedList pending = new LinkedList(); Connector() throws IOException { sel = Selector.open(); setName("Connector"); // NOI18N } // Initiate a connection sequence to the given target and add the // target to the pending-target list // void add(Target t) { SocketChannel sc = null; try { // Open the channel, set it to non-blocking, initiate connect sc = SocketChannel.open(); sc.configureBlocking(false); sc.connect(t.address); // Record the time we started t.channel = sc; t.connectStart = System.currentTimeMillis(); // Add the new channel to the pending list synchronized (pending) { pending.add(t); } // Nudge the selector so that it will process the pending list sel.wakeup(); } catch (IOException x) { if (sc != null) { try { sc.close(); } catch (IOException xx) { } } t.failure = true; t.done(); } } // Process any targets in the pending list // void processPendingTargets() throws IOException { synchronized (pending) { while (pending.size() > 0) { Target t = (Target)pending.removeFirst(); try { // Register the channel with the selector, indicating // interest in connection completion and attaching the // target object so that we can get the target back // after the key is added to the selector's // selected-key set t.channel.register(sel, SelectionKey.OP_CONNECT, t); } catch (IOException x) { // Something went wrong, so close the channel and // record the failure t.channel.close(); t.failure = true; t.done(); } } } } // Process keys that have become selected // void processSelectedKeys() throws IOException { for (Iterator i = sel.selectedKeys().iterator(); i.hasNext();) { // Retrieve the next key and remove it from the set SelectionKey sk = (SelectionKey)i.next(); i.remove(); // Retrieve the target and the channel Target t = (Target)sk.attachment(); SocketChannel sc = (SocketChannel)sk.channel(); // Attempt to complete the connection sequence try { if (sc.finishConnect()) { sk.cancel(); t.connectFinish = System.currentTimeMillis(); sc.close(); t.done(); } } catch (IOException x) { sc.close(); t.failure = true; t.done(); } } } volatile boolean shutdown = false; // Invoked by the main thread when it's time to shut down // void shutdown() { shutdown = true; sel.wakeup(); } // Connector loop // public void run() { for (;;) { try { int n = sel.select(); if (n > 0) processSelectedKeys(); processPendingTargets(); if (shutdown) { sel.close(); return; } } catch (IOException x) { x.printStackTrace(); } } } } public List<InetAddress> getActiveHosts() throws InterruptedException, IOException { port = RMIREGISTRY_PORT; InetAddress localAdd = InetAddress.getLocalHost(); //System.out.println("Local Address :"+localAdd.getHostAddress()); byte[] addr = localAdd.getAddress(); foundHosts = new ArrayList(); // Create the threads and start them up Connector connector = new Connector(); connector.start(); // Create the targets and add them to the connector for (int i=1;i<255;i++) { addr[addr.length-1]=(byte)i; Target t = new Target(InetAddress.getByAddress(addr),port); connector.add(t); } // Wait for everything to finish Thread.sleep(2000); connector.shutdown(); connector.join(); foundHosts.remove(localAdd); return foundHosts; } }