【问题标题】:Android - HttpUrlConnection is not closing. Eventually results to SocketExceptionAndroid - HttpUrlConnection 没有关闭。最终结果为 SocketException
【发布时间】:2013-12-04 05:30:14
【问题描述】:

我在运行 Jellybean (4.1 - 4.3) 的设备中遇到了一些 HttpUrlConnection 问题,其中连接未关闭,并在执行多次后导致 SocketException“打开的文件过多”。

我确实调用了 HttpUrlConnection.disconnect() 并在 finally 块中关闭了所有 Inputstream、Outputstream、Reader 和 Writers。

转到 adb shell 并执行 netstat 显示应用程序创建的所有连接都处于 CLOSE_WAIT 状态。

InputStream inputStream = httpUrlConnection.getInputStream();

// After calling inputStream.read() then the problem occurs. I think the 
// inputstream doesn't get closed even after calling close in a finally block. 
// The InputStream is a ChunkedInputStream if that helps.

我尝试过其他运行 2.3.3、4.0.3 和 4.4 的设备,没有遇到这个问题。

还有其他方法可以手动关闭连接吗?

【问题讨论】:

  • 我遇到了同样的问题,但它被隔离到了 Android Emulator。在真实设备上尝试时,它没有显示这些问题。并不是说这会对其他人有所帮助,但是我尝试了一切以解决模拟器上的问题,然后我只是在真实设备上尝试了,这不是问题。模拟器运行的是 Android 6,而真实设备运行的是 Android 9,顺便说一句。
  • 回来回复我自己的评论。我们最终也确实在真实设备上看到了这一点,但只是在一堆下载 URL 无效且未返回实际内容的情况下。所以肯定有一些东西仍然在泄漏并导致打开的文件太多。

标签: java android httpurlconnection


【解决方案1】:

我终于找到了解决方法。 Jellybean 似乎在“Keep-Alive”连接上有问题。我刚刚将 Connection=Close 添加到我的请求标头中,现在一切正常。做一个 netstat,我看到连接现在被关闭了,由于“打开的文件太多”,我不再收到 SocketException。

【讨论】:

  • 你是如何将这个添加到请求头的?能发一下代码吗?
  • @TimT connection.setRequestProperty("Connection","Close");
  • @mussharapp 救生员,这几天一直在看这个。谢谢!
  • 太棒了!我已经追了整整一周了。
  • ? ?‍♂️拯救了我的一天。
【解决方案2】:

检查您是否尝试过以下所有方法... 可能缺少一些东西..否则它应该没有任何问题。

InputStream in;
HttpsURLConnection urlConnection =null;
try {
    URL url = new URL(Url);

    urlConnection = (HttpsURLConnection) url
                     .openConnection();
    //5 Second timeout
    urlConnection.setReadTimeout(5*1000);

    in = urlConnection.getInputStream();
    int responseCode = urlConnection.getResponseCode();

    if (responseCode != HttpURLConnection.HTTP_OK) {
         InputStream errInputStream = urlConnection.getErrorStream();
        //Print error message and response code..
         errInputStream.close();
    }
    in.close();
} catch (Exception e) {
    e.printStackTrace();
} finally{
    if(urlConnection != null)
        urlConnection.disconnect();
}

【讨论】:

  • 感谢您的回答。我已经这样做了,但仍然没有解决运行 Jellybean 的设备上的问题。
【解决方案3】:

您最好调用disconnect() 并允许它进行HTTP 连接池。

【讨论】:

  • 感谢您的快速回复。我试过了,但我仍然有问题
  • 我会检查你的陈述,即一切都在 finally 块中关闭。某处有泄漏。
  • 是的,我已经检查过所有内容都在 finally 块中关闭。正如我所提到的,这只发生在运行 Jellybean 的设备(甚至模拟器)上。 Gingerbread、ICS 和 Kitkat 还可以。
  • 这表明 Jellybean 中存在错误。
【解决方案4】:

尝试改用OkHttp

添加 Maven 依赖项后,您可以执行以下操作来下载文件:

OkHttpClient okHttpClient = new OkHttpClient.Builder().build();

OutputStream output = null;

try {
  Request request   = new Request.Builder().url( download_url ).build();
  Response response = okHttpClient.newCall( request ).execute();

  if ( !response.isSuccessful() ) {
    throw new FileNotFoundException();
  }

  output = new FileOutputStream( output_path );

  output.write( response.body().bytes() );
}
finally {
  // Ensure streams are closed, even if there's an exception.
  if ( output != null ) output.flush();
  if ( output != null ) output.close();
}

切换到 OkHttp 立即修复了我们泄露的文件描述符问题,因此如果您遇到困难,值得尝试,即使以添加另一个库依赖项为代价。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-10
    • 1970-01-01
    相关资源
    最近更新 更多