【问题标题】:best Alternative for InetAddress.getByName(host).isReachable(timeout)InetAddress.getByName(host).isReachable(timeout) 的最佳替代方案
【发布时间】:2013-08-19 19:00:28
【问题描述】:

我正在尝试联系主机并使用以下代码

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

我能够从 windows ping 的主机名,并且还对其进行了跟踪,它返回了所有数据包。但是java抛出异常“主机不存在::”;

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

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

【问题讨论】:

  • 我正在测试的主机是可访问的,我可以在 Windows 中 ping 它。

标签: java ping host


【解决方案1】:

打开一个 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;
    }
}

可以在here找到相同的 Android hack:

【讨论】:

  • Windows 上ping -n 1 的问题是“目标主机无法访问”。结果返回退出代码 0,这会产生许多误报。
  • 我如何在 android 上使用它?
  • InetSocketAddress 构造函数内部使用 InetAddress.getByName 内部有很长的超时。因此,第一个解决方案并不是真正的解决方案。是一样的。
  • 这仅适用于主机名。不会对 IP 地址进行阻止操作。 “ping”可能会遇到同样的问题,因为它还必须解析一个命名主机。
【解决方案2】:

我发现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 机器。

【讨论】:

    【解决方案3】:

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

    我的代码如下:

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

    预计connect会在5秒左右抛出超时异常,但是inet不可达的时间是65秒(有人形容为假inet连接:连接说已连接 em>,但inet 无法访问)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-30
      • 1970-01-01
      • 1970-01-01
      • 2017-06-11
      相关资源
      最近更新 更多