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

时间:2013-08-19 19:00:28

标签: java ping host

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

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

我能够从Windows ping的主机名,并且还对其执行了tracert并返回所有数据包。但java抛出异常“Host is not exists ::”;

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

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

3 个答案:

答案 0 :(得分:14)

将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;
    }
}

或使用一些黑客发送实际的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的黑客here

答案 1 :(得分:0)

我发现ping -n 1 hostname也不可靠。如果你得到Reply from X.X.X.X: 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机器可供测试。

答案 2 :(得分:0)

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

我的代码如下:

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

预计connect会在大约5秒内抛出超时异常,但inet无法访问的时间为65秒(有人将其描述为假inet连接:连接说已连接,但inet无法访问)。