`
teasp
  • 浏览: 61152 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

根据主机名在局域网跨网段找IP升级版

阅读更多

    之前写了个同样功能的例子,里面用的是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);
    }
}

  

0
1
分享到:
评论

相关推荐

    什么是VLAN

     这种划分VLAN的方法是根据每个主机的网络层地址或协议类型(如果支持多协议)划分的,虽然这种划分方法是根据网络地址,比如IP地址,但它不是路由,与网络层的路由毫无关系。  这种方法的优点是用户的物理位置改变...

    6-交换机主要技术及配置 计算机技术基础

    在PC上设置相应的IP地址,使其与设备在同一网段,之后使用Telnet程序连接到交换机。 ### 交换机软件升级 升级通常涉及交换机的操作系统(IOS)。有两种主要方式: - **XMODEM方式**:速度较慢,适合小规模的数据...

    CISCO 技术大集合

    IP地址分为网络地址和主机地址二个部分,A类地址前8位为网络地址,后24位为主机地址,B类地址16位为网络地址,后16位为主机地址,C类地址前24位为网络地址,后8位为主机地址,网络地址范围如下表所示: 种类 网络...

    升级MaxDOS71

    增加多网段功能,当使用大网段时,可设置超过多少台机器自动跳跃至下一网段,理论支持无 限台客户端,增加方案功能,当首次设置完毕后,方案将自动被保存,下次使用无需再次设置. MAXDOS客户端: 增加新的引导器,主要用于...

    计算机应用技术(实用手册)

    本机病毒删除不了,解决方法是把硬盘拆下来换到别台主机上进行杀毒,要求挂上去的主机要采用正版杀毒软件,升过级的才可以 49 四.识别常见病毒,病毒一般是以隐藏形式藏匿在计算机的文件中,要把文件的隐藏属性打开...

    MaxDOS_71PXE_G115.rar

    增加多网段功能,当使用大网段时,可设置超过多少台机器自动跳跃至下一网段,理论支持无 限台客户端,增加方案功能,当首次设置完毕后,方案将自动被保存,下次使用无需再次设置. MAXDOS客户端: 增加新的引导器,主要用于...

Global site tag (gtag.js) - Google Analytics