Android HttpURLConnection抛出EOFException

15

以下是最简单的问题描述:

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

我的代理关闭了连接,但我的代码仍然尝试重用相同的连接。因此,我收到EOFException异常。

如何处理这种情况?


EOF代表文件结束。它没有可读内容。 - tolgap
因为您正在使用相同的连接,该连接仍然具有先前的数据。您必须清除所有内容。 - tolgap
2
发布一些示例代码。你只在回答的评论中声明“你做同样的事情”。如果你展示出来,我们就会知道。 - stanwise
这个问题的最终状态不清楚,请澄清。 - Snicolas
12个回答

9
我建议禁用http.keepalive系统属性。 文档中的性能部分指出,套接字连接将在可能时被重用。看起来它正在尝试重用连接,但代理已经关闭了它。 在这篇帖子中,Darrell也指出更改系统属性解决了他的问题。
System.setProperty("http.keepAlive", "false");

每次关闭连接都会减慢网络连接速度。:( 我不想这样做。 - Sudarshan Bhat
抱歉,我应该已经断开了连接。请参考http://developer.android.com/reference/java/net/HttpURLConnection.html#disconnect()。 - kturney
我不清楚您需要澄清什么,但自从这个答案发布以来,Square已经发布了他们的OkHttp库。OkHttp为您处理了Android上HTTP/S的许多特殊情况(并支持SPDY!)。 - kturney
发现三星Galaxy S III无法使用此修复方法。三星Galaxy Tab 3以及Nexus 10和Nexus 4都可以使用。我过去曾遇到过Galaxy S III表现不同的问题,所以不太确定如何处理这个问题... - DemonGyro
它在Android模拟器上不起作用,API 16的连接速度很慢。我认为问题在服务器的设置上,因为在快速连接时没有发生异常。 - CoolMind
显示剩余3条评论

6

4

我曾经在使用普通的HTTP连接时遇到了这个问题。第一次请求正常,第二次则出现EOFException异常。

最终,我通过删除...来解决了这个问题。

urlConnection.setChunkedStreamingMode(0);

...来自HttpUrlConnection。

可能是我调用的Web服务器无法很好地处理分块数据。不确定。


1

If you don't want to reuse the connection then release it.

finally {
     urlConnection.disconnect();
   }


0
  if (Build.VERSION.SDK != null
                        && Build.VERSION.SDK_INT > 13) {
                    con.setRequestProperty("Connection", "close");
                }

你能否添加一些文字来解释你的解决方案? - Kmeixner
我不确定,但是在某些版本的Android(更新版)中存在一个URL连接回收的错误,可以通过此方法修复。 - Ali Ziaee

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。

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

0

您不应该尝试重复使用相同的HttpURLConnection实例。在“类概述”的底部文档中说:

每个HttpURLConnection实例只能用于一个请求/响应对。

长连接是在不同的层级上进行管理的,参见disconnect文档: http://developer.android.com/reference/java/net/HttpURLConnection.html#disconnect()

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

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

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

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


请删除此重复答案。 - asgs

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版本之后,问题大大减少。仍在进行测试,但可能已经解决。

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

3
HttpClient存在缺陷且速度非常慢(并已被有效地弃用)。 - Norman

0

我发现重试连接可以解决问题,如此处所示:https://dev59.com/iGIk5IYBdhLWcg3wdd4l#20302767

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

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接