5

在某些情况下,我需要从客户端断开长轮询 http 请求。我对服务器进行的 HttpUrlConnection 的相关部分如下(以下所有代码都在 Thread 的 run() 方法中):

try {
    URL url = new URL(requestURL);

    connection = (HttpURLConnection) url.openConnection();
    connection.setRequestProperty("Accept-Charset", "UTF-8");
    connection.setConnectTimeout(5 * 1000);
    connection.setReadTimeout(60 * 1000);
    connection.setRequestMethod("GET");

    // read the output from the server
    reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    StringBuilder stringBuilder = new StringBuilder();

    String line = null;
    while ((line = reader.readLine()) != null) {
        stringBuilder.append(line + "\n");
    }
    Log.d(TAG, stringBuilder);
} catch (IOException ioe) {
    Log.e(TAG, ioe);
} finally {
    if (reader != null) {
        try {
            reader.close();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}

这是我第一次启动的方式,然后(经过第二次延迟)尝试取消请求:

pollThread = new PollThread();
pollThread.start();
Log.d(TAG, "pollThread started");

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        pollThread.cancelRequest();
        Log.d(TAG, "pollThread presumably cancelled");
    }
}, 1000);

这就是 cancelRequest() 方法的样子:

public void cancelRequest() {
    if (connection != null) {
        connection.disconnect();
    }
}

所以本质上,

  1. 我使用 get 请求启动 HttpUrlConnection,读取超时时间为 1 分钟
  2. 然后一秒钟后,我尝试取消之前的请求
  3. 预期的结果是,当我调用 connection.disconnect() 时,连接应该抛出 IOException

这正是各种模拟器 (2.2 - 4.0.3)、摩托罗拉 Atrix (2.3.7) 和三星 Note (4.0.1) 上发生的情况。但是在一些运行 2.2 的 HTC 设备上,尽管我明确终止了连接,但请求将保持活动状态并收到响应。我用 HTC Desire 和 HTC Wildfire 验证了这一点。

这里发生了什么?如何在所有运行 2.2+ 的设备上安全地取消此类请求?

为了您的方便,这里提供了整个代码,如果您想自己进行试驾:https ://gist.github.com/3306225

4

2 回答 2

4

这里发生了什么?

这是早期 android 版本 (Froyo 2.2) 中的一个已知错误,在排序上,套接字不能被其他线程异步关闭,并已在 Gingerbread 2.3 中修复:

问题 11705:无法使用 HttpURLConnection 关闭 HTTP 连接

如何在所有运行 2.2+ 的设备上安全地取消此类请求?

该链接中项目成员的评论:

在当前版本中工作的最佳近似值是在 HTTP 连接上设置读取和连接超时。

希望有帮助。

于 2012-08-13T03:41:38.750 回答
0

实际上,我建议您使用 Apache HttpClient lib,而不是 android 提供的默认值。

您可以从以下网址下载:http ://code.google.com/p/httpclientandroidlib/

如果你想“一路走来”,你也可以使用AndroidHttpClient“配置合理的默认设置和Android注册方案”,还可以支持cookie。你可以从这里下载它(我不记得我是什么时候找到原始的......)

这就是你使用“Get”调用的方式,我想你可以弄清楚其余的:

    InputStream isResponse = null;

    HttpGet httpget = new HttpGet(strUrl);
    HttpResponse response = getHttpClient().execute(httpget);

    HttpEntity entity = response.getEntity();
    isResponse = entity.getContent();
    responseBody = convertStreamToString(isResponse);

    /**
 * @return the mClient
 */
protected AndroidHttpClient getHttpClient() {
    if (mClient == null)
        mClient = AndroidHttpClient.newInstance(mCookieStore);
    return mClient;
}

要关闭连接:

getHttpClient().close();
于 2012-08-17T08:55:06.890 回答