问题
I am trying to reach a host and have the following code
if(!InetAddress.getByName(host).isReachable(TIMEOUT)){
throw new Exception("Host does not exist::"+ hostname);
}
The hostname I am able to ping from windows, and also did a tracert on it and it returns all the packets. But java throws out exception "Host does not exist::";
The Timeout value I experimented from giving 2000ms, to 5000ms. I tried 3000 as well. What is the cause of this problem I am not able to understand. I researched on the net and some say that InetAddress.getByName(host).isReachable(time) is not reliable and behaves according to the internal system.
What is the best alternative for this if this is true. Please suggest.
回答1:
Either open a TCP Socket to a port you think is open (22 for Linux, 139 for Windows, etc.)
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;
}
}
Or use some hack to send an actual ping. (inspired from here: 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;
}
}
Same hack for Android can be found here:
回答2:
I've found that ping -n 1 hostname
isn't reliable either. If you get Reply from X.X.X.X: Destination host unreachable.
the command actually gives an exit code of 0, thus giving you a lot of false positives.
The solution is to search for the string "TTL" in the result, as it only exists when you get a successful ping. Because the command has a pipe, you also need to use cmd /C
.
Here is an example (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);
}
I'm not sure of the unix equivalent, and don't have a unix machine to test on.
回答3:
For Android developers: the above method does not work if inet
is unavailable (more precisely when DNS cache runs in a timeout); what I found: DSN lookup always takes about 1 minute.
My code is like the following:
TIMEOUT = 5000;
socket.connect(new InetSocketAddress(ServerDomainName, Port), TIMEOUT);
It is expected that connect
throws a timeout exception within about 5 seconds, but the time was 65 seconds when inet
was unreachable (somebody describes it as fake inet
connection: Connectivity says connected, but inet
is unreachable).
来源:https://stackoverflow.com/questions/18321118/best-alternative-for-inetaddress-getbynamehost-isreachabletimeout