【问题标题】:Http connection timeout on Android not workingAndroid上的Http连接超时不起作用
【发布时间】:2011-03-05 18:24:48
【问题描述】:

我正在编写一个连接到网络服务的应用程序,如果它无法获得连接,我不希望它等待太久。因此,我设置了 httpparams 的 connectionTimeout。但这似乎没有任何作用。

为了测试,我暂时关闭了 WLAN。应用程序尝试连接很长一段时间(超过我想要的 3 秒),然后抛出 UnknownHostException。

这是我的代码:

try{
    HttpClient httpclient = new DefaultHttpClient();
    HttpParams params = httpclient.getParams();
    HttpConnectionParams.setConnectionTimeout(params, 3000);
    HttpConnectionParams.setSoTimeout(params, 3000);

    httppost = new HttpPost(URL);
    StringEntity se = new StringEntity(envelope,HTTP.UTF_8);
    httppost.setEntity(se);
    //Code stops here until UnknownHostException is thrown.
    BasicHttpResponse httpResponse = (BasicHttpResponse) httpclient.execute(httppost);

    HttpEntity entity = httpResponse.getEntity();
    return entity;

}catch (Exception e){
    e.printStackTrace();
}

有人知道我错过了什么吗?

【问题讨论】:

    标签: android http post timeout


    【解决方案1】:

    尝试这样做:

    HttpPost httpPost = new HttpPost(url);
    StringEntity se = new StringEntity(envelope,HTTP.UTF_8);
    httpPost.setEntity(se);
    
    HttpParams httpParameters = new BasicHttpParams();
    // Set the timeout in milliseconds until a connection is established.
    int timeoutConnection = 3000;
    HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
    // Set the default socket timeout (SO_TIMEOUT) 
    // in milliseconds which is the timeout for waiting for data.
    int timeoutSocket = 3000;
    HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
    
    DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
    BasicHttpResponse httpResponse = (BasicHttpResponse)  httpClient.execute(httpPost);
    
    HttpEntity entity = httpResponse.getEntity();
    return entity;
    

    然后你可以捕捉到一个可能的ConnectTimeoutException

    【讨论】:

    • 如何通知系统超时以及要处理什么异常?
    • 30 多秒后我仍然收到 UnknownHostException。在这种情况下,设备已连接到 wifi 路由器,但无法访问互联网。任何线索如何使这个呼叫处理?否则我可能会退回到外部计时器...... :(
    • @hooby3dfx 在这种情况下,外部计时器似乎是不可避免的。你有什么办法吗?
    • @Mosquito - 我确实使用了外部计时机制并在下面发布了该解决方案。
    【解决方案2】:

    使用标记的解决方案,我在 30 多秒后仍然收到 UnknownHostException。在这种情况下,设备已连接到 wifi 路由器,但无法访问互联网。

    所采取的方法是启动一个 AsyncTask,它只会尝试解析主机名。阻塞调用每250毫秒检查一次是否成功,4秒后取消任务并返回。

    这就是我为解决它所做的:

    private boolean dnsOkay = false;
    private static final int DNS_SLEEP_WAIT = 250;
    private synchronized boolean resolveDns(){
    
        RemoteDnsCheck check = new RemoteDnsCheck();
        check.execute();
        try {
            int timeSlept = 0;
            while(!dnsOkay && timeSlept<4000){
                //Log.d("RemoteDnsCheck", "sleeping");
                Thread.sleep(DNS_SLEEP_WAIT);
                timeSlept+=DNS_SLEEP_WAIT;
                //Log.d("RemoteDnsCheck", "slept");
            }
        } catch (InterruptedException e) {
    
        }
    
        if(!dnsOkay){
            Log.d("resolveDns", "cancelling");
            check.cancel(true);
            Log.d("resolveDns", "cancelled");
        }
        return dnsOkay;
    }
    
    private class RemoteDnsCheck extends AsyncTask<Void, Void, Void>{
    
        @Override
        protected Void doInBackground(Void... params) {
            try {
                Log.d("RemoteDnsCheck", "starting");
                dnsOkay = false;
                InetAddress addr = InetAddress.getByName(baseServiceURL);
                if(addr!=null){
                    Log.d("RemoteDnsCheck", "got addr");
                    dnsOkay = true;
                }
            } catch (UnknownHostException e) {
                Log.d("RemoteDnsCheck", "UnknownHostException");
            }
            return null;
        }
    
    }
    

    然后,每当我想进行网络调用时,都会在函数的开头调用它:

        if(!resolveDns()){
            return null;
        }
    

    【讨论】:

    • 这就是我要找的。谢谢老哥!
    【解决方案3】:

    见:https://stackoverflow.com/a/20031077/2609238

    问题可能出在 Apache HTTP 客户端中。请参阅 HTTPCLIENT-1098。已在 4.1.2 中修复。

    超时异常尝试反向 DNS IP,以进行日志记录。这需要额外的时间才能真正触发异常。

    【讨论】:

      【解决方案4】:

      这个方法对我有用:

      AndroidHttpTransport androidHttpTransport = new AndroidHttpTransport( endpoint, 3000) ;
      

      【讨论】:

        【解决方案5】:
        HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
        // Set the default socket timeout (SO_TIMEOUT)
        

        【讨论】:

        • 这不是问题的答案,因为该方法调用已经是下面代码的一部分; 另一个提示:使用代码格式更好地展示...
        猜你喜欢
        • 1970-01-01
        • 2012-09-19
        • 1970-01-01
        • 2010-11-27
        • 2016-01-25
        • 2017-10-10
        • 1970-01-01
        • 2020-11-18
        • 2013-03-24
        相关资源
        最近更新 更多