【问题标题】:Detecting devices on network by executing the ping command in Java通过在 Java 中执行 ping 命令检测网络上的设备
【发布时间】:2017-01-24 19:27:03
【问题描述】:

我正在尝试通过 ping 每一台设备并检查“可达”值来检测连接到我当前所在网络的设备。下面是负责执行此操作的一段代码,循环访问 IP、ping 它们并检查响应:

        for (int i = 1; i <= 254; i++) {
            String addr = IPAddress;
            addr = addr.substring(0, addr.lastIndexOf('.') + 1) + i;
            InetAddress pingAddr = InetAddress.getByName(addr);

            //skips the IP of 'this' device
            if (pingAddr.getHostAddress().equals(IPAddress)) { continue; }

            try {

                //ping command
                Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 -w 1 " + addr);
                boolean reachable = (p1.waitFor() == 0);
                if (reachable) {
                    //add to list, if reachable
                    addrs.add(pingAddr);
                }

            } catch (IOException ex) {
            } catch (InterruptedException ex) {
            }
        }

由于某种原因,这段代码只检测到一些设备。我有 3 台笔记本电脑、2 台安卓设备和 1 台 PC 进行测试。其中,它成功地检测到了 3 台笔记本电脑中的 2 台,都是 android 设备,但它未能检测到 PC。您可以注意到命令中的“-w 1”,我尝试将其设置为 100,唯一的变化是它需要很长时间才能完成,并且仍然找到相同的设备。

这个方法我也试过了:

INetAddress.isReachable(int timeout);

但情况变得更糟,因为 - 至少我发现 - 它使用 TCP 回显,并非所有设备都响应(只有我的 android 设备会响应)。

另外,ping 真的很慢。我已经把它分成了 4 个线程,但它仍然可以使用速度提升。

所以,我的最后一个问题是:为什么 ping 命令无法检测到所有设备?您还有其他方法可以实现我的目标吗?

【问题讨论】:

    标签: java android networking ping


    【解决方案1】:

    也许 PC 在防火墙后面?当您手动ping它时它会响应吗?

    为了获得更好的性能 - 试试这个:

    for (int i = 1; i <= 254; i++) {
            String addr = ipLocal;
            addr = addr.substring(0, addr.lastIndexOf('.') + 1) + i;
            InetAddress pingAddr = InetAddress.getByName(addr);
    
            //skips the IP of 'this' device
            if (pingAddr.getHostAddress().equals(ipLocal)) { continue; }
    
    
            String[] command = {"CMD", "/c", "ping -n 1 -w 1 " + addr};
            ProcessBuilder probuilder = new ProcessBuilder(command);
            Process process = probuilder.start();
    
            InputStream is = process.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line;
    
            while ((line = br.readLine()) != null) {
                CharSequence stats = "Packets: Sent = 1, Received = 1";
                if(line.contains(stats)){
                    System.out.println(line);
                    System.out.println(addr);
                    //add to list, if reachable
                    //addrs.add(pingAddr);
                }
            }
        }
    

    【讨论】:

    • 感谢您提供有用的答案。防火墙确实是“问题”,尽管其他设备(相同的操作系统)也在防火墙后面,并做出了响应。也感谢代码更新。但是,有没有办法在防火墙后面找到这样的设备?我需要此代码在某些公司网络中有用,例如能够在该网络上找到设备。如果没有,我会将这个问题标记为已接受。
    • 通过访问路由器,您可以获得有关已连接机器的信息。第二个想法是尝试 nslookup 命令。
    • 我刚刚更新了您发送给我的代码以获得更好的性能。但是,我得到了这个异常:I/System.out: java.io.IOException: Error running exec()。命令:[CMD, /c, ping -n 1 -w 1 192.168.1.245] 工作目录:null 环境:(太长了,不能放在这里..)
    • 哎呀,我不知道为什么我认为你正在使用 windows 来做这个 :) 我现在无法测试它,但尝试将命令更改为:String[] command = {"ping -n 1 -w 1 " + addr};
    【解决方案2】:

    由于位于防火墙后面(如@BuMcha 所述)或由于它们自己的设置,某些计算机不会响应 ping。如果您可以控制防火墙和个别机器,则可以通过调整各处的设置来解决此问题,但这似乎很脆弱。

    替代方法可能是发送Address Resolution Protocol (ARP) 消息。这些可能会被广播,但可能会让你以更强大的方式获得你想要的信息。我不确定如何从 Java 发送这些,但另一个问题似乎解决了这一点:Is there a way to send ARP request via Java?

    【讨论】:

      最近更新 更多