【问题标题】:How to close a persistent HTTP Connection without reading如何在不阅读的情况下关闭持久的 HTTP 连接
【发布时间】:2025-12-06 13:00:01
【问题描述】:

我有一个 URLConnection,我想根据响应代码取消它而不读取任何数据。我密切关注android training 构建了以下最小示例 由于没有连接被释放回句柄池以供重用,因此向服务器发出大量请求

private String downloadUrl(String myurl) throws IOException {
    InputStream is = null;
    try {
        URL url = new URL(myurl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setReadTimeout(10000 /* milliseconds */);
        conn.setConnectTimeout(15000 /* milliseconds */);
        conn.setRequestMethod("GET");
        conn.setDoInput(true);
        // Starts the query
        conn.connect();
        int response = conn.getResponseCode();
        Log.d(TAG, "The response code is: " + response);
        is = conn.getInputStream();

        // Do not read anything //String contentAsString = readIt(is, len);
        String contentAsString = "notReadingAnything";
        return contentAsString;
    } finally {
        if (is != null) {
            is.close();
        }
    }
}

private class DownloadWebpageTask extends AsyncTask<String, Void, String> {
    @Override
    protected String doInBackground(String... urls) {
        try {
            String result = new String();
            for (int i=0; i<100; i++) {
                result += downloadUrl(urls[0]);
            }
            return result;
        } catch (IOException e) {
            return "Unable to retrieve web page. URL may be invalid.";
        }
    }
    @Override
    protected void onPostExecute(String result) {
        Log.d(TAG, "The response is: " + result);
    }
}

尽管docs 明确声明

但是如果响应体很长,看到开头就对其余部分不感兴趣,可以关闭 InputStream

如果我不读取流,服务器会迅速达到其最大连接数 (50) 并达到 99% 的工作负载,但如果我读取它,则工作正常。我的错误是什么?

编辑:迄今为止的解决方案尝试失败(感谢@Blackbelt 为他们中的大多数)

  1. finally 块中调用conn.disconnect()
  2. finally 块中调用conn.disconnect() 而不是is.close()
  3. 在第一次调用之前设置System.setProperty("http.keepAlive", "false");
  4. 连接前设置conn.setRequestProperty("Connection", "Close");
  5. 在使用的后端服务器 (Civetweb) 上设置 "{enable_keep_alive", "no"}

【问题讨论】:

  • 仅供参考:查看conn.getResponseCode() 的实现,我还注意到一个非常有趣的陷阱:它检索 inputStream 本身,但当然不会关闭它。所以如果你使用这种方法,你必须事后检索流并自己关闭它。

标签: java android httpconnection


【解决方案1】:

您也应该致电disconnect()。根据文档

断开连接。读取响应正文后, HttpURLConnection 应该通过调用 disconnect() 来关闭。 断开连接会释放连接所占用的资源,以便它们可以 关闭或重复使用。

InputStream is = null;
HttpURLConnection conn = null;
try {
    URL url = new URL(myurl);
    conn = (HttpURLConnection) url.openConnection();

} finally {
    if (is != null) {
        is.close();
    } 
    if (conn != null) {
        conn.disconnect();
    } 
}

如果您仍然遇到问题,也可能是后端的错误

【讨论】:

  • 不幸的是,这并没有改变任何东西。我也尝试只使用conn.disconnect() 并按照here 的建议省略is.close(),但问题仍然存在
  • 服务器是你写的吗?
  • 不,是 civetweb(猫鼬的叉子)
  • 您可以尝试在openConnection 之后添加conn.setRequestProperty("Connection", "close"); 看看是否有帮助。
  • 感谢您指出一个又一个可能的解决方案,太棒了!我将它们添加到问题中以跟踪它们,因为不幸的是它们没有工作
最近更新 更多