为什么URLConnection超时时间会在6分钟后而不是5秒钟后?

7

我从我的应用程序中完全复制了这种方法,尽管它还没有完成,但如果事情不顺利,它确实会尝试为我提供超时堆栈跟踪:

protected boolean isHttpAlive()  {
  boolean isHttpOk = false;

  HttpURLConnection httpConnection = null;
  try {
    URL gurl = new URL("http://www.amazon.com/");
    URLConnection connection = gurl.openConnection();
    connection.setConnectTimeout(5 * 1000); // 5 seconds!
    httpConnection = (HttpURLConnection) connection;
    int responseCode = httpConnection.getResponseCode();
    if (responseCode == HttpURLConnection.HTTP_OK)
      isHttpOk = true;
  } 
  catch (Exception e) {                    
    e.printStackTrace();
  }
  finally {
    if (httpConnection != null)
      httpConnection.disconnect();
  }

  return isHttpOk;
}

现在在我的一个测试设备(Droid)上,当出现问题时,我确实会得到异常,但是只有在6分钟36秒后才会抛出超时异常,而不是像上面的代码中设置的5秒钟。
超时异常是由getResponseCode()引起的。
为什么?
我错过了什么?

3
我最好的猜测是你所连接的URL,例如亚马逊,有多个IP地址。根据文档中的警告:"如果主机名解析为多个IP地址,则此客户端将按照RFC 3484的顺序尝试每个地址。如果连接到这些地址的每个地址都失败,则在连接尝试抛出异常之前会经过多个超时。支持IPv6和IPv4的主机名始终至少有2个IP地址。" - jnthnjns
@Asok 我认为你说得很对。请将其作为答案发布,并突出 在连接尝试引发异常之前会经过多个超时,以便我可以接受。 - Regex Rookie
我观察到超时时间是以60秒的倍数发生的,你的5秒可能不起作用。 - sachy
2个回答

5

我最好的猜测是,你正在连接的URL(在这种情况下是亚马逊)有多个IP地址。

根据文档中的警告:

如果主机名解析为多个IP地址,则此客户端将按RFC 3484顺序尝试每个地址。如果连接到这些地址的每个地址都失败,则在连接尝试抛出异常之前将经过多个超时。同时支持IPv6和IPv4的主机名始终至少具有2个IP地址。


编辑:
我仍在研究这个问题,因为我想将我的应用程序从HTTPClient转换为URLConnection。我对于您的情况中的6分钟以上的超时时间感到不满意。

我也偶然发现了这篇博客。他建议添加connection.setReadTimeout(READ_TIMEOUT_MILLISECONDS);,不知道这是否有助于您的情况。


1
我通过设置自己的计时器来解决问题,即 Handler.postDelayed() - Regex Rookie
太好了!我可能会做同样的事情,以防万一。 - jnthnjns

-1

这种代码并不是测试连接非常有用的。连接失败的原因很多(每个IP协议栈层都可能出现问题)。 例如:你可以建立连接,但每秒只能接收一个字节,没有超时,但对用户来说并不好玩...如果你使用“www.amazon.com”作为测试,他们可能会开个玩笑(我自己也会这么做;D)


无论如何,您都应该查看苹果开发者网站上提供的可达性(Reachability)类。它提供了帮助消息来管理网络可达性。 - divol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接