10

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.

dfeuer
  • 48,079
  • 5
  • 63
  • 167

3 Answers3

15

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:

Shloim
  • 5,281
  • 21
  • 36
  • 1
    The problem with `ping -n 1` on Windows is that the "Destination host unreachable." result returns an exit code of 0, this creating many false positives. – Huon Oct 01 '14 at 05:31
  • 1
    how can i use this with android? – Prasanth A R Nov 13 '14 at 10:53
  • Ping with android: http://stackoverflow.com/questions/3905358/how-to-ping-external-ip-from-java-android – Shloim Mar 11 '15 at 10:28
  • `InetSocketAddress` constructor internally uses `InetAddress.getByName` which internally has a long timeout. So, first solution is not really a solution. It is the same. – tasomaniac Oct 18 '18 at 11:48
  • That is correct only for host by name. There will be no blocking operation for an IP address. "ping" will probably experince the same problem, since it also must resolve a named host. – Shloim Oct 18 '18 at 16:28
0

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.

Huon
  • 300
  • 3
  • 10
0

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).

Trinimon
  • 13,839
  • 9
  • 44
  • 60
Zero
  • 1