android HttpUrlConnection 设置超时无效,等待时间很长的问题


In an Android app, I'm trying to test that the user has a working Internet connection. If you are interested, there is some background in a previous question Detecting limited network connectivity in Android?


The code is basically like:

URL url = new URL(PATH);
URLConnection connection = url.openConnection();
HttpURLConnection httpUrlConnection = (HttpURLConnection) connection; 
httpUrlConnection.setDoOutput(true);  
httpUrlConnection.setDoInput(true);  
httpUrlConnection.setUseCaches(false); 
httpUrlConnection.setRequestProperty("Content-type", "application/x-java-serialized-object"); 
httpUrlConnection.setRequestMethod("POST");  
httpUrlConnection.setConnectTimeout(3000);
httpUrlConnection.setReadTimeout(300);
httpUrlConnection.connect();  
OutputStream outStrm = httpUrlConnection.getOutputStream(); 


I can control the timeouts for Connection and Socket using HttpConnectionParams. But, if my device is connected to Wifi, but the wifi has no Internet access, the error I'm getting in the exception is:


libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated with hostname)


Unable to resolve host "www.example.com": No address associated with hostname
Which looks like it timed out on a DNS lookup. Can I control the timeout of the DNS Lookup? httpClient.execute is taking about 45 seconds to fail with the exception noted above. I'd like it to give up sooner.

I did a little homework and it seems that you cannot adjust the DNS lookup timeout. So, I figured a better approach would be to an explicit DNS lookup so I could control it (and hopefully have the result cached to speed the next attempt). So that led me to the simple:

InetAddress addr = InetAddress.getByName(hostname);
but this also had a 45 second timeout. Others had mentioned that there was no control of the timeout for getByName(). Finally, I stumbled on a simple solution, just launch the lookup in a separate thread and manage your own timeout. 


This blog post shows this quite well.

private static boolean testDNS(String hostname) {
  try
  {
    DNSResolver dnsRes = new DNSResolver(hostname);
    Thread t = new Thread(dnsRes);
    t.start();
    t.join(1000);
    InetAddress inetAddr = dnsRes.get();            
    return inetAddr != null;
  }
  catch(Exception e)
  { 
    return false;
  }
}


private static class DNSResolver implements Runnable {
    private String domain;
    private InetAddress inetAddr;


    public DNSResolver(String domain) {
        this.domain = domain;
    }


    public void run() {
        try {
            InetAddress addr = InetAddress.getByName(domain);
            set(addr);
        } catch (UnknownHostException e) {                
        }
    }


    public synchronized void set(InetAddress inetAddr) {
        this.inetAddr = inetAddr;
    }
    public synchronized InetAddress get() {
        return inetAddr;
    }
}


Using this I can first test if the device can resolve the host name, then if it successful to the full connectivity test.
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值