15

这是最简单的问题。

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

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

我该如何处理这种情况?

4

12 回答 12

9

我建议禁用 http.keepalive 系统属性。文档的性能部分表明套接字连接将在可能的情况下被重用。听起来它正在尝试重用连接,但代理已经关闭了它。在这篇文章中,Darrell 还表示更改系统属性解决了他的问题。

System.setProperty("http.keepAlive", "false");
于 2012-09-11T20:22:14.807 回答
6

结果他们已经在 1 月 8 日 [1] 在 Android 中修复了这个问题。该修复基本上将旧连接标记为已回收并在内部重试请求。

为了暂时解决这个问题,我建议在遇到 EOFException 时重试请求,并设置重试限制以防止 stackoverlows。

  1. https://android.googlesource.com/platform/libcore/+/19aa40c81c48ff98ccc7272f2a3c41479b806376
于 2013-02-18T23:59:20.260 回答
4

正常的 HTTP 连接也有这个问题。第一个请求正常,第二个请求失败并出现 EOFException。

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

urlConnection.setChunkedStreamingMode(0);

...来自 HttpUrlConnection。

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

于 2012-11-28T13:02:58.090 回答
1

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

finally {
     urlConnection.disconnect();
   }

于 2012-09-16T06:44:07.627 回答
0

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

  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();
    }
于 2012-09-16T15:56:21.547 回答
0

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

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

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

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

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

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

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

于 2015-01-08T18:04:57.420 回答
0

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

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

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

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

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

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

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

于 2015-01-08T16:59:35.790 回答
0

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

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

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

if (retries > 0) {
    connection.setRequestProperty("Connection", "close");
}
于 2014-05-22T17:59:40.883 回答
0

也许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 大大减少了问题。仍在测试,但甚至可能已解决。

于 2014-01-15T02:42:53.470 回答
0
  if (Build.VERSION.SDK != null
                        && Build.VERSION.SDK_INT > 13) {
                    con.setRequestProperty("Connection", "close");
                }
于 2016-04-12T19:59:02.517 回答
-1

试试这个代码:`

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();
    }

`

于 2012-09-07T13:51:59.793 回答
-1

将流转换为字符串:`

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();

}`
于 2012-09-07T14:03:27.737 回答