之前写了个同样功能的例子,里面用的是TCP socket通信逐个IP进行查找,效率比较低。现在改成UDP进行广播,在限定时间内没找到会放弃。本版本效率应该高很多。当然,条件是被查找的机器也运行以下代码:
public class IpHostInLan1 { private static final int PORT = 4322; private static final String NOT_FOUND = "NotFound"; private ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>(); private static IpHostInLan1 instance = new IpHostInLan1(); private DatagramSocket ss = null; private byte[] sendPacket = "Hi".getBytes(); private IpHostInLan1() { new Thread() { public void run() { try { String localHost = InetAddress.getLocalHost().getHostName(); ss = new DatagramSocket(PORT); System.out.println("--------Listening to " + PORT + "----------"); byte[] buffer = new byte[4]; byte[] response = localHost.getBytes(); while (true) { DatagramPacket packet = new DatagramPacket(buffer, buffer.length); try { ss.receive(packet); SocketAddress peerAddr = packet.getSocketAddress(); DatagramPacket responsePacket = new DatagramPacket(response, response.length, peerAddr); ss.send(responsePacket); System.out.println("Server received : " + new String(packet.getData(), 0, packet.getLength())); } catch (IOException e) { e.printStackTrace(); } } } catch (Exception e) { e.printStackTrace(); } } }.start(); } public static IpHostInLan1 instance() { return instance; } /** * 获取主机名对应的IP。如果map中没有那么到局域网里面去找。 * @param host * @return */ public String getIp(String host, long timeout) { String ip = map.get(host); if (ip != null) { //之前找过,现在不找了 if (ip.equals(NOT_FOUND)) return null; return ip; } ip = search(host, timeout); if (ip == null) { map.put(host, NOT_FOUND); } else { map.put(host, ip); } return ip; } private String search(final String host, final long timeout) { String ip = null; try { ip = InetAddress.getByName(host).getHostAddress(); } catch (Exception e) { System.out.println("failed to find " + host + " in my own IP segment."); } if (ip == null) { try { final DatagramSocket ds = new DatagramSocket(); ds.setSoTimeout(100); //开启检查接收结果的线程 ExecutorService service = Executors.newFixedThreadPool(1); final Future<String> future = service.submit(new Callable<String>() { public String call() { long startTime = System.currentTimeMillis(); byte[] buffer = new byte[32]; while (System.currentTimeMillis()-startTime < timeout) { DatagramPacket packet = new DatagramPacket(buffer, buffer.length); try { ds.receive(packet); String response = new String(packet.getData(), 0, packet.getLength()); String resultIp = packet.getAddress().getHostAddress(); if (host.equals(response)) { return resultIp; } map.put(host, resultIp); //如果有其它回应,缓存起来 } catch (IOException e){} } return null; } } ); //开启发送线程 new Thread() { public void run() { send(future, ds); } }.start(); if (ip == null) { try { //在指定时间内等待结果,如果时间到,那么放弃查找 ip = future.get(timeout, TimeUnit.MILLISECONDS); } catch (Exception e){} } service.shutdownNow(); //不用发了 ds.close(); //放弃查找,关闭该socket } catch (SocketException e) { e.printStackTrace(); } } return ip; } /** * 往各个IP发送数据包,如果已经得到结果则停止发送。 * @param future * @param ds * @return */ private String send(Future<String> future, DatagramSocket ds) { String ip = null; try { String[] segs = InetAddress.getLocalHost().getHostAddress().split("[.]"); String prefix = segs[0] + "." + segs[1] + "."; int localSeg = Integer.valueOf(segs[2]); int i = 1; while (localSeg + i < 256 || localSeg - i > -1) { if (localSeg + i < 256) { if (false == send(prefix + (localSeg + i) + ".", ds)) break; try { //检查是否已经有结果了 ip = future.get(1, TimeUnit.MILLISECONDS); } catch (Exception e) {} if (ip != null) break; } if (localSeg - i > -1) { if (send(prefix + (localSeg - i) + ".", ds)) break; try { //检查是否已经有结果了 ip = future.get(1, TimeUnit.MILLISECONDS); } catch (Exception e) {} if (ip != null) break; } i++; } } catch (Exception e) { e.printStackTrace(); } return ip; } private boolean send(String prefix, DatagramSocket ds) { System.out.format("Searching in %s segment...\n", prefix); for (int i=2; i<256; i++) { String ip = prefix + i; if (!send(ds, ip)) { return false; } } return true; } /** * 往指定的IP发送一个数据包 * @param ds * @param ip */ private boolean send(DatagramSocket ds, String ip) { try { InetAddress addr = InetAddress.getByName(ip); DatagramPacket p = new DatagramPacket(sendPacket, sendPacket.length, addr, PORT); ds.send(p); } catch (Exception e) { // e.printStackTrace(); return false; } return true; } public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line = null; while ((line=br.readLine()).equalsIgnoreCase("exit") == false) { System.out.println(IpHostInLan1.instance().getIp(line, 2000)); } System.exit(0); } }
相关推荐
DNS和IP主机表可以帮助解析域名到IP地址,以及维护静态的主机名到IP地址映射。 **7.11 s10接口** s10接口是另一种串行接口,用于与其他设备进行连接。 **7.12 Reset命令** Reset命令用于重置交换机到出厂默认...
这种划分VLAN的方法是根据每个主机的网络层地址或协议类型(如果支持多协议)划分的,虽然这种划分方法是根据网络地址,比如IP地址,但它不是路由,与网络层的路由毫无关系。 这种方法的优点是用户的物理位置改变...
在PC上设置相应的IP地址,使其与设备在同一网段,之后使用Telnet程序连接到交换机。 ### 交换机软件升级 升级通常涉及交换机的操作系统(IOS)。有两种主要方式: - **XMODEM方式**:速度较慢,适合小规模的数据...
IP地址分为网络地址和主机地址二个部分,A类地址前8位为网络地址,后24位为主机地址,B类地址16位为网络地址,后16位为主机地址,C类地址前24位为网络地址,后8位为主机地址,网络地址范围如下表所示: 种类 网络...
增加多网段功能,当使用大网段时,可设置超过多少台机器自动跳跃至下一网段,理论支持无 限台客户端,增加方案功能,当首次设置完毕后,方案将自动被保存,下次使用无需再次设置. MAXDOS客户端: 增加新的引导器,主要用于...
- **全局配置模式**: 在此模式下可以进行设备的全局配置,如设置主机名、配置接口等。 **2.2 命令模式的切换** - 通过`enable`命令进入特权模式。 - 使用`configure terminal`进入全局配置模式。 **2.3 CLI命令的...
本机病毒删除不了,解决方法是把硬盘拆下来换到别台主机上进行杀毒,要求挂上去的主机要采用正版杀毒软件,升过级的才可以 49 四.识别常见病毒,病毒一般是以隐藏形式藏匿在计算机的文件中,要把文件的隐藏属性打开...
增加多网段功能,当使用大网段时,可设置超过多少台机器自动跳跃至下一网段,理论支持无 限台客户端,增加方案功能,当首次设置完毕后,方案将自动被保存,下次使用无需再次设置. MAXDOS客户端: 增加新的引导器,主要用于...