best Alternative for InetAddress.getByName(host).isReachable(timeout)

拈花ヽ惹草 提交于 2019-12-30 04:35:07

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!