24

I want to test whether a remote system is reachable using Java or in other words "send a ping" using Java. This functionality should be encapsulated in a method with boolean value, for example

public boolean isReachable(String ip) {
   // what to do :-)
}

I've tested the Java Process class, but I don't think that it is the best way to do this, because of the complex output handling with OutputBuffers.

Process proc = Runtime.getRuntime().exec("ping " + ip);

Another possibility would be creating a Socket Connection and handle thrown exceptions, but if the remote system is a "naked" unix system, there might be no Socket on the other side :-) Additionally, I'd like to be able to set a timeout, when a remote system is not reachable.

So how could I do this? Thank you!

strauberry
  • 4,189
  • 5
  • 34
  • 50

5 Answers5

55
InetAddress.getByName(ip).isReachable(timeout);
andypandy
  • 1,117
  • 7
  • 9
  • 10
    can we check whether a specific port is reachable? – tasomaniac Oct 27 '12 at 18:23
  • 1
    This function should not be used in production setups where you don't have full control over privileges, firewalls, etc.. see: http://stackoverflow.com/questions/9922543/why-does-inetaddress-isreachable-return-false-when-i-can-ping-the-ip-address – ssindelar Jun 01 '16 at 11:07
  • Nice, simple and clean. – xdevs23 Sep 07 '16 at 06:56
12

InetAddress.getByName(host).isReachable(timeOut) (seen here)

michael667
  • 3,241
  • 24
  • 32
  • 7
    isReachable() cannot be trusted to reliably ping hosts outside of the local subnet. The most likely reason is that windows is using ICMP ping while isReachable() is failing to use it. This is the case up to at least Java 6. – flash Oct 07 '11 at 09:40
  • 5
    There's a comment in the native `isReachable0` method implementation (in `Inet4AddressImpl.c) which says "Windows implementation of ICMP & RAW sockets is too unreliable for now. Therefore it's best not to try it at all and rely only on TCP. We may revisit and enable this code in the future." ` – Mister Smith Oct 07 '11 at 09:59
  • 1
    Confirmed, in my WXP test machine this command defaults to a TCP connection on port 7 (echo). It returns reachable even for IP's that do not exist, or with the firewall blocked. – Mister Smith Oct 07 '11 at 10:18
5

It looks like you are using Linux so you will probably find that isReachable() is unreliable (because you will not have permissions to send ICMP packets, and very few servers have the Echo service running).

If that is the case then I think you will need to use spawn a Process in the way you suggest, but I recommend using a command like:

   ping -c 1 hostname

This will terminate after one attempt and you can then examine the exit status of the process - much more reliable than parsing standard output.

Ping returns 0 for success non-zero on failure.

Paul Cager
  • 1,910
  • 14
  • 21
2

From my experience there is no 100% reliable way to do this you have to chose by trying multiple options or combining them, but isReachable() can't be used as reliable option. Better pure java option I think will be something like this:

private static boolean isReachable(String host, int openPort, int timeOutMillis) {
    try {
        try (Socket soc = new Socket()) {
            soc.connect(new InetSocketAddress(host, openPort), timeOutMillis);
        }
        return true;
    } catch (IOException ex) {
        return false;
    }
}

And if you want to check if host is accessible via web/browser here is it:

private static boolean hostsWebApp(String host, int timeOutMillis) {
    boolean isReachable = isReachable(host, 80, timeOutMillis);
    if(!isReachable) {
        return isReachable(host, 443, timeOutMillis);
    } else {
        return true;
    }
}
sedrakpc
  • 508
  • 4
  • 18
  • Better option, please add soc.close(). But still does not provide consistent results. Some hosts can only be accessed after multiple retries. – muratozyurt Oct 12 '22 at 05:57
  • 1
    No need for close since it is inside the try-with-resource. – sedrakpc Oct 13 '22 at 03:21
  • You're right. I had a different problem where multiple threads were involved and the network had to retry the soc.connect() multiple times. Thanks. – muratozyurt Oct 14 '22 at 06:42
1

I know this question has found its answer but I'd like to add my code just for "copy-paste".

public boolean isIpReachable(String ip, int timeout){
    boolean state = false;

    try {
        state = InetAddress.getByName(ip).isReachable(timeout);
    } catch (IOException e) {
        //Parse error here
    }

    return state;
}
Alpha2k
  • 2,212
  • 7
  • 38
  • 65