通过在 Java 中执行 ping 命令检测网络上的设备
Posted
技术标签:
【中文标题】通过在 Java 中执行 ping 命令检测网络上的设备【英文标题】:Detecting devices on network by executing the ping command in Java 【发布时间】: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 命令无法检测到所有设备?您还有其他方法可以实现我的目标吗?
【问题讨论】:
【参考方案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?
【讨论】:
以上是关于通过在 Java 中执行 ping 命令检测网络上的设备的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 QProcess 通过 Ping 检测“网络不可达”?
计算机网络 网络层 ICMP协议 ping和traceroute介绍