Сетевые интерфейсы

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 425
351
homepage.mac.com
#1
часто возникают вопросы по работе с сетью и сетевыми интерфейсами...
для LS адаптировать не стал..., куски на java
итераторы реализовал для 8-ой java (уж извиняйте), в коде оставил ссылки на оригиналы
Java:
//https://docs.oracle.com/javase/tutorial/networking/nifs/listing.html
import java.io.*;
import java.net.*;
import java.util.*;
import static java.lang.System.out;
 
public class ListNets {
 
	public static void main(String args[]) throws SocketException {
		Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
		for (NetworkInterface netint : Collections.list(nets))
			displayInterfaceInformation(netint);
	}
 
	static void displayInterfaceInformation(NetworkInterface netint) throws SocketException {
		out.printf("Display name: %s\n", netint.getDisplayName());
		out.printf("Name: %s\n", netint.getName());
		Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
		for (InetAddress inetAddress : Collections.list(inetAddresses)) {
			out.printf("InetAddress: %s\n", inetAddress);
		}
		out.printf("\n");
	 }
}
Java:
import org.apache.commons.net.util.SubnetUtils;
import java.net.*;
import java.util.*;
import static java.lang.System.out;
class SomeClass{
....
	public static <T> T[] concatAll(T[] first, T[]... rest) {
		//http://stackoverflow.com/questions/80476/how-can-i-concatenate-two-arrays-in-java
		int totalLength = first.length;
		for (T[] array : rest) {
			totalLength += array.length;
		}
		T[] result = Arrays.copyOf(first, totalLength);
		int offset = first.length;
		for (T[] array : rest) {
			System.arraycopy(array, 0, result, offset, array.length);
			offset += array.length;
		}
		return result;
	}
 
	public static String[] getRangeFromLocal(int ifNum) {
		String[] res = null;
		NetworkInterface liface;
		try {
			if (ifNum >= 0) {
				liface = Collections.list(NetworkInterface.getNetworkInterfaces()).get(ifNum);
				//displayInterfaceInformation(liface);
				//res=new String[]{liface.getInterfaceAddresses().get(0).getAddress().getHostAddress()};
				res = new SubnetUtils(liface.getInterfaceAddresses().get(0).getAddress().getHostAddress() + "/" + String.valueOf(liface.getInterfaceAddresses().get(0).getNetworkPrefixLength())).getInfo().getAllAddresses();
			} else {
				res = Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
//				networkInterface.getInterfaceAddresses().stream()
						.filter(iface -> {
							boolean ret = true;
							try {
								ret = !iface.isLoopback();
							} catch (SocketException e) {
								e.printStackTrace();
							}
							return ret;
						})
						.map(iface -> {
							return new SubnetUtils(iface.getInterfaceAddresses().get(0).getAddress().getHostAddress() +
									"/" + String.valueOf(iface.getInterfaceAddresses().get(0).getNetworkPrefixLength())).getInfo().getAllAddresses();
						})
						.reduce(new String[]{}, (s1, s2) -> {
							return concatAll(s1, s2);
						});
			}
		} catch (SocketException e) {
			e.printStackTrace();
		}
		return res;
	}
}
 

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 425
351
homepage.mac.com
#2
докручено - получение списка сетей (именно списка, в виде массива строк с адресами) основываясь на адресах и масках их интерфейсов локального компа
 
сканирование сетей (реально быстрое, т.к. в отдельном потоке и неблокирующее)
Java:
package kodiForm;
/*
* @(#)Ping.java 1.2 01/12/13
* Connect to each of a list of hosts and measure the time required to complete
* the connection.  This example uses a selector and two additional threads in
* order to demonstrate non-blocking connects and the multithreaded use of a
* selector.
*
* Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* -Redistributions of source code must retain the above copyright
*
* -Redistributions of source code must retain the above copyright
* notice, this  list of conditions and the following disclaimer.
*
* -Redistribution in binary form must reproduct the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
*
* -Redistribution in binary form must reproduct the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Oracle nor the names of
* contributors may be used to endorse or promote products derived
*
* Neither the name of Oracle nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any
* kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
* EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY
* DAMAGES OR LIABILITIES  SUFFERED BY LICENSEE AS A RESULT OF  OR
* RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR
* ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE
* FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT,
* SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF
* THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN
*
* This software is provided "AS IS," without a warranty of any
* kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
* EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY
* DAMAGES OR LIABILITIES  SUFFERED BY LICENSEE AS A RESULT OF  OR
* RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR
* ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE
* FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT,
* SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF
* THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that Software is not designed, licensed or
* intended for use in the design, construction, operation or
* maintenance of any nuclear facility.
*
* You acknowledge that Software is not designed, licensed or
* intended for use in the design, construction, operation or
* maintenance of any nuclear facility.
*/
 
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.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
 
 
public class Ping {
 
	// The default daytime port
	static int DAYTIME_PORT = 13;
	// The default http port
	static int HTTP_PORT = 80;
	// the default ssh port
	static int SSH_PORT = 22;
	// The port we'll actually use
	static int port = SSH_PORT;
 
 
	// Representation of a ping target
	//
	//
	static class Target {
 
		private InetSocketAddress address;
		private SocketChannel channel;
		private Exception failure;
		private long connectStart;
		private long connectFinish = 0;
		private boolean shown = false;
		private boolean connected = false;
 
		Target(String host) {
			try {
				address = new InetSocketAddress(InetAddress.getByName(host),
						port);
			} catch (IOException x) {
				failure = x;
			}
		}
 
		void show() {
			String result;
			if (connectFinish != 0)
				result = Long.toString(connectFinish - connectStart) + "ms";
			else if (failure != null)
				result = failure.toString();
			else
				result = "Timed out";
			System.out.println(address + " : " + result);
			shown = true;
		}
 
		public InetSocketAddress getAddress() {
			InetSocketAddress res=null;
			if (connectFinish != 0) {
				res = address;
				connected = true;
			}
			return res;
		}
	}
 
	// Thread for printing targets as they're heard from
	//
	static class Printer
			extends Thread {
		LinkedList pending = new LinkedList();
 
		Printer() {
			setName("Printer");
			setDaemon(true);
		}
 
		void add(Target t) {
			synchronized (pending) {
				pending.add(t);
				pending.notify();
			}
		}
 
		public void run() {
			try {
				for (; ; ) {
					Target t = null;
					synchronized (pending) {
						while (pending.size() == 0)
							pending.wait();
						t = (Target) pending.removeFirst();
					}
					t.show();
				}
			} catch (InterruptedException x) {
				return;
			}
		}
 
	}
 
 
	// Thread for connecting to all targets in parallel via a single selector
	//
	//
	static class Connector
			extends Thread {
		Selector sel;
		Printer printer;
 
		// 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(Printer pr) throws IOException, InterruptedException {
			printer = pr;
			sel = Selector.open();
			setName("Connector");
		}
 
		// 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);
				// Open the channel, set it to non-blocking, initiate connect
				sc = SocketChannel.open();
				sc.configureBlocking(false);
 
				boolean connected = sc.connect(t.address);
 
				// Record the time we started
				t.channel = sc;
				t.connectStart = System.currentTimeMillis();
 
				if (connected) {
					t.connectFinish = t.connectStart;
					sc.close();
					printer.add(t);
				} else {
					// 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 = x;
				printer.add(t);
			}
		}
 
		// 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);
						// 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 = x;
						printer.add(t);
						// Something went wrong, so close the channel and
						// record the failure
						t.channel.close();
						t.failure = x;
						printer.add(t);
 
					}
				}
 
			}
		}
 
		// 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();
						printer.add(t);
					}
				} catch (IOException x) {
					sc.close();
					t.failure = x;
					printer.add(t);
				}
			}
		}
 
 
		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 static void main(String[] args)
			throws InterruptedException, IOException {
		if (args.length < 1) {
			System.err.println("Usage: java Ping [port] host...");
			return;
		}
		int firstArg = 0;
 
		// If the first argument is a string of digits then we take that
		// to be the port number to use
		if (Pattern.matches("[0-9]+", args[0])) {
			port = Integer.parseInt(args[0]);
			firstArg = 1;
		}
 
		// Create the threads and start them up
		Printer printer = new Printer();
		printer.start();
		Connector connector = new Connector(printer);
		connector.start();
 
		// Create the targets and add them to the connector
		LinkedList<Target> targets = new LinkedList();
/*		for (int i = firstArg; i < args.length; i++) {
		Target t = new Target(args[i]);
		targets.add(t);
		connector.add(t);
	}
*/
		Arrays.asList(NetUtils.getRangeFromLocal(3)).forEach(saddr -> {
			Target t = new Target(saddr);
			targets.add(t);
			connector.add(t);
		});
		// Wait for everything to finish
		Thread.sleep(500);
		connector.shutdown();
		connector.join();
		List<Target> filtered= targets.stream()
				.filter(t -> t.getAddress() != null)
				.collect(Collectors.toList());
				//.forEach(t -> System.out.println(t.address.toString()));
		System.out.println("*************");
				filtered.forEach(t -> System.out.println(t.address.toString()));
 
		// Print status of targets that have not yet been shown
/*		for (Iterator i = targets.iterator(); i.hasNext(); ) {
			Target t = (Target) i.next();
			if (!t.shown)
				t.show();
		}
*/
	}
 
}
Чтобы видеть этот контент необходимо: Войти или зарегистрироваться

дополнил (чутка) получением откликнувшихся хостов, порт использовал 22 (там по коду - сверху). Код на сайте поломатый - я его поправил
в коде заюзан метод из предыдущего поста (NetUtils.getRangeFromLocal(3))
 
Последнее редактирование модератором:

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 425
351
homepage.mac.com
#3
список хостов подсети я получал под свои нужды (сканирования), в апачевсой либе есть просто проверка на принадлежность хоста подсети
еще есть UPnP с cling - не вижу смысла выкладывать, просто FYI для методов сканирования
 

garrick

Well-Known Member
Lotus team
26.10.2009
865
68
Москва
#4

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 425
351
homepage.mac.com
#5
Если я всё правильно понял, то
Чтобы видеть этот контент необходимо: Войти или зарегистрироваться
были уже в 5-й Java. Т.о. в 8-ом Лотусе должно работать.
разумеется, но синтаксис для лямбд меня прельщает больше ;), а вот они "не будут работать"
 

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 425
351
homepage.mac.com
#6
внес коррекции
код с сайта - жрал сокеты, сделал их убиение в finally, вынес фильтры для сетей, добавил фильтры для IPV4 и ввел ограничение маски сетей (до
Чтобы видеть этот контент необходимо: Войти или зарегистрироваться
):
Java:
package kodiForm;
 
import org.apache.commons.net.util.SubnetUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.io.IOException;
import java.net.*;
import java.util.*;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
 
import static java.lang.System.out;
/**
 * Created by mike on 29.10.15.
 */
public class NetUtils {
	private static int TIMEOUT=500;
	private static short MASQ_LIIM=20;//limit prefix masq len for restrict lage network scan
	private static final String resPath="./res";
		private static final Logger LOG=LoggerFactory.getLogger(new Throwable() .getStackTrace()[0].getClassName());;
	private static Predicate<NetworkInterface> notLoopback=iface -> {
		boolean ret=false;
		try {
			ret = !iface.isLoopback();
		} catch (SocketException e) {
			e.printStackTrace();
		}
		return ret;};
	private static Predicate<NetworkInterface> notFake=iface -> {
		boolean ret=false;
		try {
			ret = !iface.isLoopback() & !iface.isPointToPoint()
					& (Collections.list(iface.getInetAddresses()).size()>0)
					& !iface.isVirtual();
		} catch (SocketException e) {
			e.printStackTrace();
		}
		return ret;};
	private static Predicate<InterfaceAddress> masq=addr -> {
		boolean ret=false;
		ret = addr.getNetworkPrefixLength()>=MASQ_LIIM;
		return ret;};
	private static Predicate<InterfaceAddress> ipv4=addr -> {
		LOG.info("filter IPV4 for:" +addr.getAddress().getHostAddress());
		return addr.getAddress() instanceof Inet4Address;
	};
 
	//http://commons.apache.org/proper/commons-net/apidocs/org/apache/commons/net/util/SubnetUtils.html
	//http://stackoverflow.com/questions/2942299/converting-cidr-address-to-subnet-mask-and-network-address
 
	/**
	 *
	 * @param address tested address
	 * @param subnet CIDR notation
	 * @return true if included
	 */
	public static boolean checkIpBySubNet(String address, String subnet){
		SubnetUtils utils = new SubnetUtils(subnet);
		return utils.getInfo().isInRange(address);
	}
 
	/**
	 *
	 * @param address tested address
	 * @param subnetaddr address from subnet (any known)
	 * @param mask mask
	 * @return true if included
	 */
	public static boolean checkIpBySubNet(String address, String subnetaddr, String mask){
		SubnetUtils utils = new SubnetUtils(subnetaddr, mask);
		return utils.getInfo().isInRange(address);
	}
	public static List<String> accessibleRange(String anyIp) {
		ArrayList<String> res=new ArrayList<String>();
		InetAddress[] addrs=null;
		try {
			 addrs= InetAddress.getAllByName(anyIp);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		for(InetAddress addr: addrs){
			try {
				if (addr.isReachable(1000)){res.add(addr.getHostAddress());}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return res;
	}
 
	public static List<String> accessibleRange() {
		ArrayList<String> res=new ArrayList<String>();
		for(String saddr: getRangeFromLocal(0)) {
			InetAddress addr = null;
			try {
				addr = InetAddress.getByName(saddr);
				if (addr.isReachable(TIMEOUT)) {
					res.add(addr.getHostAddress());
				} else {
					System.out.println("Is Not reachiable: " + addr.getHostAddress());
				}
			} catch (UnknownHostException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return res;
	}
	public static <T> T[] concatAll(T[] first, T[]... rest) {
		//http://stackoverflow.com/questions/80476/how-can-i-concatenate-two-arrays-in-java
		int totalLength = first.length;
		for (T[] array : rest) {
			totalLength += array.length;
		}
		T[] result = Arrays.copyOf(first, totalLength);
		int offset = first.length;
		for (T[] array : rest) {
			System.arraycopy(array, 0, result, offset, array.length);
			offset += array.length;
		}
		return result;
	}
 
	public static List<NetworkInterface> getIfaces() throws SocketException {
		return Collections.list(NetworkInterface.getNetworkInterfaces()).stream().filter(notFake).collect(Collectors.toList());
	}
 
	public static String[] getRangeFromLocal(int ifNum) {
		String[] res = {};
		NetworkInterface liface;
		try {
			if (ifNum >= 0) {
				//liface = Collections.list(NetworkInterface.getNetworkInterfaces()).get(ifNum);
				//liface=NetworkInterface.getByIndex(ifNum); // by real num in interfaces list
				liface=getIfaces().get(ifNum);
				//displayInterfaceInformation(liface);
				//res=new String[]{liface.getInterfaceAddresses().get(0).getAddress().getHostAddress()};
				//filter only IPV4
				res=liface.getInterfaceAddresses().stream()
						.filter(ipv4)
						.filter(masq)
						.map(a->{return new SubnetUtils(a.getAddress().getHostAddress() + "/" + String.valueOf(a.getNetworkPrefixLength())).getInfo().getAllAddresses();})
						.reduce(new String[] {}, (s1,s2)->{return concatAll(s1, s2);});
				/*for(InterfaceAddress addr:liface.getInterfaceAddresses()){
					LOG.info(addr.getAddress().getHostAddress() + "/" +addr.getNetworkPrefixLength());
					res = concatAll(res,new SubnetUtils(addr.getAddress().getHostAddress() + "/" + String.valueOf(addr.getNetworkPrefixLength())).getInfo().getAllAddresses());
				}*/
//			  res = new SubnetUtils(liface.getInterfaceAddresses().get(0).getAddress().getHostAddress() + "/" + String.valueOf(liface.getInterfaceAddresses().get(0).getNetworkPrefixLength())).getInfo().getAllAddresses();
			} else {
				res = Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
//				networkInterface.getInterfaceAddresses().stream()
						.filter(notFake)
						//for each interface (excluding localhost, virtual, P2P)
						//return String[]
						.map(iface -> {
							return iface.getInterfaceAddresses().stream()
									.filter(ipv4)
									.filter(masq)
									//for each ipv4 address on interface
									.map(a->{return new SubnetUtils(a.getAddress().getHostAddress() + "/" + String.valueOf(a.getNetworkPrefixLength())).getInfo().getAllAddresses();})
									.reduce(new String[] {}, (s1,s2)->{return concatAll(s1, s2);});
//							return new SubnetUtils(iface.getInterfaceAddresses().get(0).getAddress().getHostAddress() +
//									"/" + String.valueOf(iface.getInterfaceAddresses().get(0).getNetworkPrefixLength())).getInfo().getAllAddresses();
						})
						//return combined String[] (for all interfaces)
						.reduce(new String[]{}, (s1, s2) -> {
							return concatAll(s1, s2);
						});
			}
		} catch (SocketException e) {
			e.printStackTrace();
		}
		return res;
	}
 
	static void displayInterfaceInformation(NetworkInterface netint) throws SocketException {
		//https://docs.oracle.com/javase/tutorial/networking/nifs/listing.html
		out.printf("Display name: %s\n", netint.getDisplayName());
		out.printf("Name: %s\n", netint.getName());
		out.printf("Index: %s\n",netint.getIndex());
		Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
		for (InetAddress inetAddress : Collections.list(inetAddresses)) {
			out.printf("InetAddress: %s\n", inetAddress);
		}
		out.printf("\n");
	}
 
	public static void main(String args[]){
		//createFtpUser("test","fortestonly");
		//startFtp("1680");
		//accessibleRange().forEach(addr->System.out.println(addr));
		Enumeration<NetworkInterface> nets = null;
		try {
			nets = NetworkInterface.getNetworkInterfaces();
			for (NetworkInterface netint : Collections.list(nets))
				if (!netint.isLoopback() & !netint.isPointToPoint()
						& (Collections.list(netint.getInetAddresses()).size()>0)
						& !netint.isVirtual())displayInterfaceInformation(netint);
		} catch (SocketException e) {
			e.printStackTrace();
		}
		if (args.length < 1) {
			System.err.println("Usage: java Ping ifaceNum");
			return;
		}
		int firstArg =-1;
		if (Pattern.matches("[0-9]+", args[0])) {
			firstArg = Integer.parseInt(args[0]);
		}
//firstArg=-1;
		out.printf("Param: %d\n", firstArg);
		out.println(Arrays.toString(getRangeFromLocal(firstArg)));
		//return 0;
	}
 
}
Java:
package kodiForm;
/*
 * @(#)Ping.java 1.2 01/12/13
 * Connect to each of a list of hosts and measure the time required to complete
 * the connection.  This example uses a selector and two additional threads in
 * order to demonstrate non-blocking connects and the multithreaded use of a
 * selector.
 *
 * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
 *
 * отстальная часть отмазок, в посте выше
 */
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.io.IOException;
import java.io.InterruptedIOException;
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.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
 
public class Ping {
	private static final Logger LOG= LoggerFactory.getLogger(new Throwable() .getStackTrace()[0].getClassName());
	// The default daytime port
	static int DAYTIME_PORT = 13;
	// The default http port
	static int HTTP_PORT = 80;
	// the default ssh port
	static int SSH_PORT = 22;
	// The port we'll actually use
	static int port = SSH_PORT;
	static short TIMEOUT_SELECT=10;//10ms timeout for nio select
	static boolean logConnect=true;
 
	static final Broker broker=new Broker();
 
	static void add2broker(Object o){
		broker.add(o);
		logConnect=false;
	}
 
	// Representation of a ping target
	//
	//
	class Target {
 
		private InetSocketAddress address;
		private SocketChannel channel;
		private Exception failure;
		private long connectStart;
		private long connectFinish = 0;
		private boolean shown = false;
		private boolean connected = false;
 
		Target(String host) {
			try {
				address = new InetSocketAddress(InetAddress.getByName(host),
						port);
			} catch (IOException x) {
				failure = x;
			}
		}
 
		void show() throws IOException {
			String result;
			if (connectFinish != 0) {
				result = Long.toString(connectFinish - connectStart) + "ms";
				broker.publish(address.getAddress().getHostAddress());
			}else if (failure != null)
				result = failure.toString();
			else
				result = "Timed out";
			//channel.close();
			//System.out.println(address + " : " + result);
			if (logConnect) LOG.info((address + " : " + result));
			shown = true;
		}
 
		public InetSocketAddress getAddress() {
			InetSocketAddress res=null;
			if (connectFinish != 0) {
				res = address;
				connected = true;
			}
			return res;
		}
	}
 
	// Thread for printing targets as they're heard from
	//
	static class Printer
			extends Thread {
		LinkedList pending = new LinkedList();
 
		Printer() {
			setName("Printer");
			setDaemon(true);
		}
 
		void add(Target t) {
			synchronized (pending) {
				pending.add(t);
				pending.notify();
			}
		}
 
		public void run() {
			try {
				for (; ; ) {
					Target t = null;
					synchronized (pending) {
						while (pending.size() == 0)
							pending.wait();
						t = (Target) pending.removeFirst();
					}
						t.show();
				}
			} catch (InterruptedException | IOException x) {
				return;
			}
		}
 
	}
 
 
	// Thread for connecting to all targets in parallel via a single selector
	//
	//
	class Connector
			extends Thread {
		Selector sel;
		Printer printer;
 
		// 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(Printer pr) throws IOException, InterruptedException{
			printer = pr;
			sel = Selector.open();
			setName("Connector");
		}
 
		// 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);
/* <p> If this channel is in non-blocking mode then an invocation of this
* method initiates a non-blocking connection operation.  If the connection
* is established immediately, as can happen with a local connection, then
* this method returns <tt>true</tt>.  Otherwise this method returns
* <tt>false</tt> and the connection operation must later be completed by
* invoking the {@link #finishConnect finishConnect} method.
*/
				boolean connected = sc.connect(t.address);
 
				// Record the time we started
				t.channel = sc;
				t.connectStart = System.currentTimeMillis();
 
				if (connected) {
					t.connectFinish = t.connectStart;
					sc.close();
					printer.add(t);
				} else {
					// 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 = x;
				printer.add(t);
			}
		}
 
		// 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 = x;
						printer.add(t);
					}
				}
 
			}
		}
 
		// 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();
						printer.add(t);
					}
				} catch (IOException x) {
					sc.close();
					t.failure = x;
					printer.add(t);
				}
			}
*/
			//http://tutorials.jenkov.com/java-nio/selectors.html
			Set<SelectionKey> selectedKeys = sel.selectedKeys();
 
			Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
 
			while(keyIterator.hasNext()) {
 
				SelectionKey key = keyIterator.next();
				keyIterator.remove();
 
				if(key.isAcceptable()) {
					// a connection was accepted by a ServerSocketChannel.
 
				} else if (key.isConnectable()) {
					// a connection was established with a remote server.
					Target t = (Target) key.attachment();
					SocketChannel sc = (SocketChannel) key.channel();
					try {//test connection for reject
						if (sc.finishConnect()) {
							key.cancel();
							t.connectFinish = System.currentTimeMillis();
							sc.close();
							printer.add(t);
						}
					} catch (IOException x) {
						sc.close();
						t.failure = x;
						printer.add(t);
					}
 
				} else if (key.isReadable()) {
					// a channel is ready for reading
 
				} else if (key.isWritable()) {
					// a channel is ready for writing
				}
 
			}
		}
 
 
		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(TIMEOUT_SELECT);
					if (n > 0)
						processSelectedKeys();
					processPendingTargets();
					if (shutdown) {
						sel.close();
						//sel=null;
						return;
					}
				} catch (InterruptedIOException e){
					try {
						sel.close();
					} catch (IOException e1) {
						LOG.error("failed within Interruption!",e1);
						//e1.printStackTrace();
					}
					return;
				} catch (IOException x) {
					LOG.error("failed!",x);
					//x.printStackTrace();
				}
			}
		}
 
	}
	public List<Target>  pingIface(int iface, long timeout) throws IOException, InterruptedException {
		Printer printer = new Printer();
		printer.start();
		Connector connector = new Connector(printer);
		connector.start();
		List<Target> filtered=null;
		LinkedList<Target> targets = new LinkedList();
		try {
 
		// Create the targets and add them to the connector
/*		for (int i = firstArg; i < args.length; i++) {
		Target t = new Target(args[i]);
		targets.add(t);
		connector.add(t);
	}
*/
			//final Connector finalConnector = connector;
			Arrays.stream(NetUtils.getRangeFromLocal(iface)).forEach(saddr -> {
				Target t = new Target(saddr);
				targets.add(t);
				connector.add(t);
			});
			// Wait for everything to finish
			if (timeout>0) Thread.sleep(timeout);
 
			filtered = targets.stream()
					.filter(t -> t.getAddress()!= null)
					.collect(Collectors.toList());
 
			if (logConnect) {
			//.forEach(t -> System.out.println(t.address.toString()));
				LOG.info("*************");
				filtered.forEach(t -> LOG.info(String.valueOf(t.address)));
			}
			//System.out.println(""+filtered.parallelStream().map(t ->String.valueOf(t.address)).collect(Collectors.toList()));
/*
			connector.shutdown();
			connector.join();
			printer.interrupt();
*/
		} finally {
			connector.shutdown();
			connector.interrupt();
			printer.interrupt();
			//clear all opened Sockets
			targets.forEach(t -> {
				try {
					if (t.channel!=null && t.channel.isOpen()){
						if (logConnect)LOG.info("*channel Address: "+String.valueOf(t.channel.getRemoteAddress()));
						t.channel.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			});
			LOG.info("************* Finally exit");
		}
		// Print status of targets that have not yet been shown
/*		for (Iterator i = targets.iterator(); i.hasNext(); ) {
			Target t = (Target) i.next();
			if (!t.shown)
				t.show();
		}
*/
		return filtered;
	}
 
	public static void main(String[] args)
			throws InterruptedException, IOException {
/*
		if (args.length < 1) {
			System.err.println("Usage: java Ping [port] host...");
			return;
		}
		int firstArg = 0;
 
		// If the first argument is a string of digits then we take that
		// to be the port number to use
		if (Pattern.matches("[0-9]+", args[0])) {
			port = Integer.parseInt(args[0]);
			firstArg = 1;
		}
*/
 
		if (args.length < 1) {
			System.err.println("Usage: java Ping ifaceNum");
			return;
		}
		class My extends Component{
			@Subscription
			public void onString(String s) {
				LOG.info("My String: "+s);
				//System.out.println("String - " + s);
			}
 
		}
		//add2broker(new My());
		int firstArg = -1;
		if (Pattern.matches("[0-9]+", args[0])) {
			firstArg = Integer.parseInt(args[0]);
		}
		Ping ping=new Ping();
		ping.pingIface(firstArg, 500);
	}
 
}
 

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 425
351
homepage.mac.com
#7
кому интересно читать про nio -
Чтобы видеть этот контент необходимо: Войти или зарегистрироваться

в чем смысл - одна треда открывает кучу сокетов параллельно!
кол-во сокетов - зависит от подсети для каждого интерфейса
по умолчанию - боянит по всем сетевым интерфейсам, кот. есть IPV4 и кот. проходят по маске (ну и остальные фильтры)
время сканирования очень мало - отклик от всех рабочих адресов, в локалке, получается менее 500мс
влияние
Java:
int select(long timeout)
в 10мс не обнаружил
понятно что проверка открытия сокета - это не полная доступность сервиса, но существенно сократит диапазон проверки
Важно! если в локалке есть
Чтобы видеть этот контент необходимо: Войти или зарегистрироваться
- могут быть вопросы ;)
 
код брокера, в данном контексте, не так важен - потому не выложил