【问题标题】:Android HttpURLConnection throwing EOFExceptionAndroid HttpURLConnection 抛出 EOFException
【发布时间】:2012-09-01 09:38:17
【问题描述】:

这是最简单的问题。

我使用 HttpUrlConnection 对象通过代理创建到我的服务器的 HTTPS 连接。

我的代理关闭了连接,但我的代码仍然尝试重用相同的连接。所以我得到了EOFException。

我该如何处理这种情况?

【问题讨论】:

  • EOF = 文件结尾。它没有什么可读的。
  • 因为你使用的是同一个连接,它仍然有之前的数据。您必须清除所有内容。
  • 发布一些示例代码。您只在 cmets 中声明“您也这样做”来回答。如果您出示它,我们就会知道。
  • 这个问题的最终状态还不清楚。请澄清。

标签: android httpurlconnection eofexception


【解决方案1】:

我建议禁用 http.keepalive 系统属性。 documentation 的性能部分表示将尽可能重用套接字连接。听起来它正在尝试重用连接,但代理已经关闭了它。在this post,Darrell 还表示更改系统属性解决了他的问题。

System.setProperty("http.keepAlive", "false");

【讨论】:

  • 每次都会关闭连接并减慢网络连接速度。 :(我不想那样做。
  • 我同意重用连接会更好。你确定你从连接中得到的InputStream在使用后是关闭的吗?
  • 如果我关闭输入流,我将释放流所持有的所有资源,包括底层套接字。所以在这种情况下连接不能被重用。
  • 对不起,我应该把连接断开developer.android.com/reference/java/net/…
  • 我不清楚你想澄清什么,但自从这个答案以来,Square 已经发布了他们的OkHttp 库。 OkHttp 为您处理 Android 上 HTTP/S 的许多特性(并且支持 SPDY!)。
【解决方案2】:

事实证明,他们已于 1 月 8 日 [1] 在 Android 中修复了此问题。该修复基本上将旧连接标记为已回收,并在内部重试请求。

要暂时解决此问题,我建议在遇到 EOFException 时重试请求,并设置重试限制以防止堆栈溢出。

  1. https://android.googlesource.com/platform/libcore/+/19aa40c81c48ff98ccc7272f2a3c41479b806376

【讨论】:

    【解决方案3】:

    我在正常的 HTTP 连接中也遇到了这个问题。第一个请求正常,第二个请求失败并出现 EOFException。

    最终我通过删除来修复它...

    urlConnection.setChunkedStreamingMode(0);
    

    ...来自 HttpUrlConnection。

    我可能是我正在调用的网络服务器无法很好地处理分块数据。不知道。

    【讨论】:

      【解决方案4】:

      如果您不想重复使用连接,请释放它。

      finally {
           urlConnection.disconnect();
         }

      【讨论】:

        【解决方案5】:

        您可以使用此方法从服务器中选择数据,然后将输入修剪转换为字符串,然后您可以解析以供进一步使用。`

          public static InputStream getUrlData(final String url)
                throws URISyntaxException, ClientProtocolException, IOException {
            final DefaultHttpClient client = new DefaultHttpClient();
            final HttpGet method = new HttpGet(new URI(url));
            final HttpResponse res = client.execute(method);
            return res.getEntity().getContent();
            }
        

        【讨论】:

        • HttpClient 有问题而且速度很慢(实际上已被弃用。)
        【解决方案6】:

        也许httpClient“有更多错误”并且已被弃用,但 JellyBean 的这个问题是一个大问题。我正在使用 Ksoap2,所以我尝试了所有建议的答案。

        • System.setProperty("http.keepAlive", "false");
        • httpTransportSE.getServiceConnection().setRequestProperty("Connection", "close");
        • httpTransportSE.getServiceConnection().disconnect();

        没有任何效果 - 我的解决方案是将我正在使用的 Ksoap2 版本从 3.1.1 回滚到 2.6.5。使用 2.6.5 大大减少了问题。仍在测试,但可能已经解决。

        【讨论】:

          【解决方案7】:

          我发现重试连接可以解决问题,如下所示:https://stackoverflow.com/a/20302767/2520390

          确保在递归调用之前关闭连接。

          此外,我在连接中添加了以下内容以关闭连接,但我不确定它是否有帮助:

          if (retries > 0) {
              connection.setRequestProperty("Connection", "close");
          }
          

          【讨论】:

            【解决方案8】:

            您不应该尝试重用相同的 HttpURLConnection 实例。 “类概述”最底线的docs

            HttpURLConnection 的每个实例都可以用于一个 请求/响应对。

            Keep-Alive 连接在不同级别工作,请参阅断开连接文档: http://developer.android.com/reference/java/net/HttpURLConnection.html#disconnect()

            与其他 Java 实现不同,这不一定会关闭 可以重用的套接字连接。您可以禁用所有连接 通过在之前将 http.keepAlive 系统属性设置为 false 来重用 发出任何 HTTP 请求。

            因此,您应该始终使用新的 HttpURLConnection 并让套接字池处理重用。

            在 Froyo (2.2) 之前的版本中,keep-alive 连接显然存在错误,因此建议在这些旧设备上禁用 keep-alive。

            在我的情况下,EOFException 是由于我的服务器未发送完整响应引起的,请参阅此处的详细信息:https://stackoverflow.com/a/27845172/2335025

            【讨论】:

              【解决方案9】:

              您不应该尝试重用相同的 HttpURLConnection 实例。 “类概述”最底线的docs

              HttpURLConnection 的每个实例都可以用于一个 请求/响应对。

              Keep-Alive 连接在不同级别工作,请参阅断开连接文档: http://developer.android.com/reference/java/net/HttpURLConnection.html#disconnect()

              与其他 Java 实现不同,这不一定会关闭 可以重用的套接字连接。您可以禁用所有连接 通过在之前将 http.keepAlive 系统属性设置为 false 来重用 发出任何 HTTP 请求。

              因此,您应该始终使用新的 HttpURLConnection 并让套接字池处理重用。如果它试图重用已被服务器关闭的套接字,可能会出现问题,这个问题的答案涉及:Android HttpUrlConnection EOFException

              在 Froyo (2.2) 之前的版本中,keep-alive 连接显然存在错误,因此建议在这些旧设备上禁用 keep-alive。

              在我的情况下,EOFException 是由于我的服务器未发送完整响应引起的,请参阅此处的详细信息:https://stackoverflow.com/a/27845939/2335025

              【讨论】:

              • 请删除这个重复的答案。
              【解决方案10】:
                if (Build.VERSION.SDK != null
                                      && Build.VERSION.SDK_INT > 13) {
                                  con.setRequestProperty("Connection", "close");
                              }
              

              【讨论】:

              • 您能否添加一些文字来解释您的解决方案?
              • 我不确定,但某些版本的 android(较新的)在回收的 url 连接上存在错误,可以通过此修复。
              【解决方案11】:

              试试这个代码:`

              Httppost方法:

                  HttpParams httpParams = new BasicHttpParams();
                  HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_MILLISEC);
                  HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_MILLISEC);
                  HttpClient client = new DefaultHttpClient(httpParams);
                  HttpPost request = new HttpPost("put_url");
                  request.setHeader("Content-Type", "application/xml");
              
                  String file = resourceXml();
              
              
                  StringEntity se = null;
                  try {
                      se = new StringEntity(file);
                  } catch (UnsupportedEncodingException e1) {
              
                      e1.printStackTrace();
                  }
              
                  se.setContentEncoding("UTF-8");
                  se.setContentType("application/xml");
                  request.setEntity(se);
                  HttpResponse response = null;
                  try {
                      response = client.execute(request);
                  } catch (ClientProtocolException e1) {
              
                      e1.printStackTrace();
                  } catch (IOException e1) {
              
                      e1.printStackTrace();
                  }
              
                  HttpEntity entity = response.getEntity();
                  InputStream is = null;
                  try {
                      is = entity.getContent();
                  } catch (IllegalStateException e) {
              
                      e.printStackTrace();
                  } catch (IOException e) {
              
                      e.printStackTrace();
                  }
                  String _response = convertStreamToString(is);
              
                  Log.i(TAG, "Response:" + _response);
                  // Check if server response is valid code
                  int res_code = response.getStatusLine().getStatusCode();
                  Log.i(TAG, "status_code" + res_code);
                  try {
                      is.close();
                  } catch (IOException e) {
              
                      e.printStackTrace();
                  }
              

              `

              【讨论】:

              • httpClient 的 bug 远比 httpurlconnection 多。推荐使用HttpURLConnection。
              • 使用方法convertStreamToString();
              【解决方案12】:

              将流转换为字符串:`

              private static String convertStreamToString(InputStream is) {
              
                  BufferedReader reader = new BufferedReader(new InputStreamReader(is),
                          8192);
                  StringBuilder sb = new StringBuilder();
              
                  String line = null;
                  try {
                      while ((line = reader.readLine()) != null) {
                          sb.append((line + "\n"));
                      }
                  } catch (IOException e) {
                      e.printStackTrace();
                  } finally {
                      try {
                          is.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
                  return sb.toString();
              
              }`
              

              【讨论】:

              • 这正是我在里面所做的。
              • 我第一次连接一切都很好。当我第二次这样做时,它在conn.connect() 上显示 EOFException。只有当我在设备级别设置代理时才会发生这种情况。
              猜你喜欢
              • 1970-01-01
              • 2013-10-16
              • 1970-01-01
              • 2013-03-11
              • 2013-02-16
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多