【问题标题】:Android: connection timeout not working (connection waits forever)Android:连接超时不起作用(连接永远等待)
【发布时间】:2012-09-19 13:41:53
【问题描述】:

我有一个连接到服务器的应用程序。我设置了超时,断开设备与互联网的连接并尝试执行发布请求以查看是否调用了超时,但连接一直在等待。这是我的代码:

private static final int TIMEOUT_OPS = 3000 ;
private HttpClient mHttpClient;

public String sendToken(String token) throws IOException, AuthenticationException {
    JSONArray jsonData = new JSONArray();
    jsonData.put(token);

    final HttpPost post = prepareJSONRequest(jsonData.toString(), SEND_TOKEN_METHOD);
    HttpClient httpClient = getConnection();
    Log.i(TAG, "Sending request");
    final HttpResponse resp;
    try{
        resp = httpClient.execute(post);
    }catch(Exception e){
        e.printStackTrace();
        return null;
    }
    Log.i(TAG, "Got response");
    ...
}

private HttpPost prepareJSONRequest(String rest_data, String method) throws AssertionError {
    AbstractHttpEntity entity = null;
    try {
        final ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair(KEY_PARAM_METHOD, method));
        params.add(new BasicNameValuePair(KEY_PARAM_INPUT_TYPE, JSON));
        params.add(new BasicNameValuePair(KEY_PARAM_RESPONSE_TYPE, JSON));
        params.add(new BasicNameValuePair("rest_data", rest_data));
        entity = new UrlEncodedFormEntity(params, HTTP.UTF_8);
        final HttpPost post = new HttpPost(mServer);
        post.addHeader(entity.getContentType());
        post.setEntity(entity);
        return post;

    } catch (final UnsupportedEncodingException e) {
        // this should never happen.
        throw new AssertionError(e);
    }
}

private HttpClient getConnection() {
    if (mHttpClient == null) {
        // registers schemes for both http and https
        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
        HttpProtocolParams.setUseExpectContinue(params, false);
        HttpConnectionParams.setConnectionTimeout(params, TIMEOUT_OPS);
        HttpConnectionParams.setSoTimeout(params, TIMEOUT_OPS);
        ConnManagerParams.setTimeout(params, TIMEOUT_OPS);
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        final SSLSocketFactory sslSocketFactory = SSLSocketFactory.getSocketFactory();
        sslSocketFactory.setHostnameVerifier(SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        if (!mNoCertValidation)
            registry.register(new Scheme("https", sslSocketFactory, 443));
        else
            registry.register(new Scheme("https", new EasySSLSocketFactory(), 443));
        ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(params, registry);
        mHttpClient = new DefaultHttpClient(manager, params);

    }
    return mHttpClient;
}

如果我执行此代码,我的日志会显示“发送请求”,但不会打印异常或“得到响应”。为什么它不起作用?

【问题讨论】:

  • 您是否在 Manifest 文件中设置了 Internet 权限?
  • 如果您没有 Internet,DNS 请求将失败,但您无法控制 DNS 超时。最终你应该得到一个 UnknownHostException,但这可能需要几分钟。在这种情况下,最好的办法是在发出 HTTP 请求的同时在单独的线程中启动计时器。如果在 HTTP 请求完成之前计时器已关闭,您可以中止 HTTP 请求。
  • 谢谢大卫,我会这样做的。
  • 是的,我总是接受有用的答案,以便其他有同样问题的人知道如何解决它 =)

标签: android http post timeout


【解决方案1】:

如果您没有 Internet,则 DNS 请求将失败,但您无法控制 DNS 超时。最终你应该得到一个 UnknownHostException,但这可能需要几分钟。在这种情况下,最好的办法是在发出 HTTP 请求的同时在单独的线程中启动计时器。如果在 HTTP 请求完成之前计时器已关闭,您可以中止 HTTP 请求。

【讨论】:

  • 你的解释听起来很合理。可以做的另一件事是监听网络状态的变化,如stackoverflow.com/questions/3307237/… 中所述。
  • @wojci 是的。但是,我的经验表明,如果您的连接不稳定/不良,您经常会看到连接超时和 DNS 超时,但您看不到网络状态事件发生变化(因为理论上您有连接,所以它不起作用)。对于用户启用/禁用连接或您处于根本没有数据连接的情况,网络状态更改是有用/可靠的。只是我个人的经验。
  • 这听起来很有意义,但在尝试使用ThreadThread.sleep(time) 以及Timer.schedule() 调用HttpGet.abort() 之后,在此方法没有IOException 被抛出和@ 987654327@ 在大约 30 秒后执行。
猜你喜欢
  • 1970-01-01
  • 2011-10-12
  • 1970-01-01
  • 2011-03-06
  • 1970-01-01
  • 2011-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多