【问题标题】:Catch timeout exception when connecting TCP socket to hostname将 TCP 套接字连接到主机名时捕获超时异常
【发布时间】:2015-02-23 11:53:36
【问题描述】:

我需要捕获与主机名和端口的 TCP 连接的超时异常,其中包括对主机名进行 DNS 查找。如果我连接到数字 IP 地址和端口,我可以设置一个短暂的超时并快速捕获异常,但如果我使用域名,DNS 查找可能需要 5 分钟才能引发异常。

如何让这个操作更快超时?

Socket socketconnectionObjet = new Socket();
socketconnectionObjet.connect(new InetSocketAddress(url, port),
                              3  * 1000);          

【问题讨论】:

  • +1 这并不是一个听起来那么简单的问题,因为它是 DNS 查找而不是后续的套接字操作超时。也许您可以先明确地进行 DNS 查找?

标签: java android tcp tcpclient


【解决方案1】:

看看:Socket#connect。您请求函数在 5 分钟后失败 (3 * 1000)。阅读提供的文档以获取更多信息。

【讨论】:

  • 不正确。您自己的链接显示超时以毫秒为单位。
【解决方案2】:

首先,重要的是要了解您实际上需要使两个单独的进程超时 - DNS 查找和连接本身。如果两者都必须在某个超时范围内,则解决方案必须如下所示:

long startTime = System.currentTimeMillis();
InetAddress destination = doDnsLookupWithTimeout(MAX_TIMEOUT);
long remaniningTime = MAX_TIMEOUT - (System.currentTimeMillis() - startTime);
if (remainingTime > 0){ //we still have time to connect
    connectWithTimeout(remainingTime);
}

好消息是,很容易使套接字连接超时,您已经这样做了。然而,坏消息是在 DNS 查找上强制执行超时更加困难。不幸的是,Java 的 InetAddress.getByName() 不接受超时参数,因此调用可能会阻塞很长一段时间(我最近 had an issue 在 windows 上的一些反向 DNS 调用阻塞了 4.5 秒)。

一种解决方案是简单地避免 Java 的本机 DNS 查找实用程序,并使用支持超时的外部库,例如 DnsJavaSimpleResolver,它有一个 setTimeout() 方法。

想到的另一个解决方案是在一个单独的线程中执行 DNS 查找,并使用带有超时值的 Thread.join()Future.get() 等待该线程完成其业务。如果第二个线程及时完成,则使用剩余时间进行连接。如果没有,并且您在 Thread.joinFuture.get 上超时,那么您已经超时。

【讨论】:

    猜你喜欢
    • 2011-11-02
    • 2011-05-12
    • 2014-07-09
    • 2019-10-21
    • 2012-01-19
    • 2016-12-01
    • 2012-06-21
    • 2011-01-30
    • 2019-07-11
    相关资源
    最近更新 更多