我有一个networking上的设备,我试图ping通我的Java程序。 通过我的Windows命令提示符,我可以ping通设备地址,并在地址上做tracert。
在线上,我已经看到,为了通过Java执行ping操作,您必须执行以下操作:
InetAddress.getByName(address).isReachable(timeout);
但是,当我在我的设备地址上使用此代码时,它总是在我的程序中返回false。 我正在使用具有良好超时值的正确IPv4地址。 另外,如果我使用本地主机地址,它工作正常。
为什么我可以通过CMD ping设备,但不通过我的程序? 我曾在各地听说这不是一个真正的平台 。
有没有更好的方法来模拟Java中的ping?
谢谢
isReachable()
将使用ICMP ECHO REQUEST
,否则将尝试在目标主机的端口7(Echo)上建立TCP连接。
因此,如果您的客户端没有权限执行ICMP ECHO REQUEST
,那么您的问题可能是在客户端计算机上没有足够的权限来执行此操作,或者服务器上存在端口7问题。 可能在你的情况下,你需要解决一方或另一方得到这个工作。
我在OSX和Linux客户端上测试了以下内容,并在测试其他OSX,Linux和Windows server计算机的可用性时使用。 我没有Windows机器来运行这个客户端。
import java.io.IOException; import java.net.InetAddress; public class IsReachable { public static void main(final String[] args) throws IOException { final InetAddress host = InetAddress.getByName(args[0]); System.out.println("host.isReachable(1000) = " + host.isReachable(1000)); } }
从我在这里读到的。 显然,Windows限制和ICMP PING
作为Windows 2000之前的系统调用在Windows上不受支持,所以它默认尝试连接到端口7,并且在您试图“到达”的机器上被阻止。 Java不支持新的本地系统调用。 权限是基于Unix的系统,因为它们需要root来发送ICMP
数据包。
如果你想推出自己的Windows原生JNI ICMP PING
的Windows 2000和更新有IcmpSendEcho功能 。
当我需要在Windows,Linux和OSX上进行真正的ICMP ping(我还没有测试其他系统)时,我使用这个函数(从这篇文章中 )。
public static boolean isReachableByPing(String host) { try{ String cmd = ""; if(System.getProperty("os.name").startsWith("Windows")) { // For Windows cmd = "ping -n 1 " + host; } else { // For Linux and OSX cmd = "ping -c 1 " + host; } Process myProcess = Runtime.getRuntime().exec(cmd); myProcess.waitFor(); if(myProcess.exitValue() == 0) { return true; } else { return false; } } catch( Exception e ) { e.printStackTrace(); return false; } }
有点晚了,但我试图做同样的事情,我偶然发现。
一种解决方法,为我工作,我使用的是直接使用命令行ping。
public static boolean ping(String host) { boolean isReachable = false; try { Process proc = new ProcessBuilder("ping", host).start(); int exitValue = proc.waitFor(); System.out.println("Exit Value:" + exitValue); if(exitValue == 0) isReachable = true; } catch (IOException e1) { System.out.println(e1.getMessage()); e1.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } return isReachable; }
其中一个原因是您指定的超时时间太短。 我有一个类似的问题,但是当我增加超时到一个合适的值,isReachable调用返回一个正确的值。
我看到很多与这个问题有关的不好的代码。 我工作的代码是(网站不知道要正确解析我的代码文件):
public class Test { public static boolean isReachablebyPing(String ip) { try { String command; if(System.getProperty("os.name").toLowerCase().startsWith("windows")) { // For Windows command = "ping -n 2 " + ip; } else { // For Linux and OSX command = "ping -c 2 " + ip; } Process proc = Runtime.getRuntime().exec(command); StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT"); outputGobbler.start(); proc.waitFor(); return checkAvailability(outputGobbler.getOutputLines()); } catch(IOException | InterruptedException ex) { Logger.getLogger(StreamGobbler.class.getName()).log(Level.SEVERE, null, ex); } return false; } public static void main(String... args) { String ip = "10.20.20.17"; // false in my case String ip1 = "10.20.20.100"; // true in my case System.out.println(ip + " is avalaible " + isReachablebyPing(ip)); System.out.println(ip1 + " is avalaible " + isReachablebyPing(ip1)); } private static boolean checkAvailability(List<String> outputLines) { for(String line : outputLines) { if(line.contains("unreachable")) { return false; } if(line.contains("TTL=")) { return true; } } return false; } } class StreamGobbler extends Thread { protected InputStream is; protected String type; protected List<String> outputLines; StreamGobbler(InputStream is, String type) { this.is = is; this.type = type; outputLines = new ArrayList<>(); } public List<String> getOutputLines() { return outputLines; } @Override public void run() { try { InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line; while((line = br.readLine()) != null) { outputLines.add(line); } } catch(IOException ex) { Logger.getLogger(StreamGobbler.class.getName()).log(Level.SEVERE, null, ex); } } }
对于从没有权限的Java容易ping,我使用http://www.icmp4j.org
这非常容易使用:
final IcmpPingRequest request = IcmpPingUtil.createIcmpPingRequest (); request.setHost ("www.google.org"); // repeat a few times for (int count = 1; count <= 4; count ++) { // delegate final IcmpPingResponse response = IcmpPingUtil.executePingRequest (request); // log final String formattedResponse = IcmpPingUtil.formatResponse (response); System.out.println (formattedResponse); // rest Thread.sleep (1000); }
在使用Windows机器 ping一个公共IP地址的情况下,使用这不会有所帮助:
String ipAddress = "192.168.1.10"; InetAddress inet = InetAddress.getByName(ipAddress); boolean reachable = inet.isReachable(5000);
注意:文档指出:
如果可以获得特权,典型的实现将使用ICMP ECHO REQUEST,否则将尝试在目标主机的端口7(Echo)上建立TCP连接 。
我试过,但结果不准确。
对我来说,真正解决的是我们的同事写的类,发送真正的ICMP ping,并根据IP状态返回true或false。
奇怪的InetAddress.isReachable()问题