InetAddress.getByName(host).isReachable(timeout)的最佳替代方案

我正在尝试访问主机并拥有以下代码

if(!InetAddress.getByName(host).isReachable(TIMEOUT)){ throw new Exception("Host does not exist::"+ hostname); } 

我可以从Windows ping主机名,并在其上执行tracert并返回所有数据包。 但java抛出exception“Host is not exists ::”;

我给出的超时值是2000ms,到5000ms。 我也尝试了3000。 我无法理解这个问题的原因是什么。 我在网上研究过,有人说InetAddress.getByName(host).isReachable(time)不可靠,并且根据内部系统行事。

如果这是真的,最好的选择是什么。 请建议。

打开TCP套接字到您认为已打开的端口(Linux为22,Windows为139等)

 public static boolean isReachableByTcp(String host, int port, int timeout) { try { Socket socket = new Socket(); SocketAddress socketAddress = new InetSocketAddress(host, port); socket.connect(socketAddress, timeout); socket.close(); return true; } catch (IOException e) { return false; } } 

或者使用一些hack来发送实际的ping。 (灵感来自: http : //www.inprose.com/en/content/icmp-ping-in-java )

 public static boolean isReachableByPing(String host) { try{ String cmd = ""; if(System.getProperty("os.name").startsWith("Windows")) cmd = "cmd /C ping -n 1 " + host + " | find \"TTL\""; else cmd = "ping -c 1 " + host; Process myProcess = Runtime.getRuntime().exec(cmd); myProcess.waitFor(); return myProcess.exitValue() == 0; } catch( Exception e ) { e.printStackTrace(); return false; } } 

Android的相同hack可以在这里找到:

我发现ping -n 1 hostname也不可靠。 如果您收到Reply from XXXX: Destination host unreachable. 该命令实际上给出了退出代码0,从而给你很多误报。

解决方案是在结果中搜索字符串“TTL”,因为它仅在您成功ping时才存在。 由于该命令具有管道,因此还需要使用cmd /C

这是一个例子(Windows):

 public boolean isReachable(String hostname) throws IOException, InterruptedException { Process p = Runtime.getRuntime().exec( "cmd /C ping -n 1 "+hostname+" | find \"TTL\"" ); return (p.waitFor() == 0); } 

我不确定unix等价物,并且没有unix机器可以测试。

对于Android开发人员:如果inet不可用,则上述方法不起作用(更确切地说,当DNS缓存在超时运行时); 我发现:DSN查找总是需要大约1分钟。

我的代码如下:

 TIMEOUT = 5000; socket.connect(new InetSocketAddress(ServerDomainName, Port), TIMEOUT); 

预计connect会在大约5秒内引发超时exception,但是当inet无法访问时,时间为65秒(有人将其描述为假连接:连接已连接 ,但无法访问)。