Apache HttpClient 4.0 无法在 Android 上的套接字超时

Posted

技术标签:

【中文标题】Apache HttpClient 4.0 无法在 Android 上的套接字超时【英文标题】:Apache HttpClient 4.0 failing to timeout for socket on Android 【发布时间】:2011-11-01 12:22:55 【问题描述】:

我正在开发一个需要使用 HttpClient 才能将文件从 android 设备上传到 Web 服务器的 Android 应用程序。我上传的文件最大可以达到 1 Gb,因此如果设备在上传过程中断开连接,可能会发生超时。奇怪的是,我为套接字设置的超时似乎没有任何效果。每当我失去连接而不是引发 SocketTimeoutException 时,应用程序就会挂起。

我尝试使用:

HttpConnectionParams.setConnectionTimeout(params, CrashLogParams.TIMEOUT);
HttpConnectionParams.setSoTimeout(params, CrashLogParams.TIMEOUT);

但这仅适用于连接超时,不适用于套接字超时。我也试过了:

HttpParams p = httpclient.getParams();
p.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 10000);
p.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000);

我知道连接超时有效的原因是,执行后我会收到连接超时异常

httpclient.execute(httppost);

在上传过程中连接丢失时,应用程序似乎挂起,但在应用程序成功连接到服务器之后。

为了测试我的应用,我在不同时间禁用了网络以查看应用的反应。如果我在发送请求之前禁用网络,我会收到连接错误,我的应用程序可以正常处理它,但如果我在上传期间禁用它,应用程序会挂起。当然,我是通过 AsyncTasks 执行所有这些请求,因此主 UI 线程不会崩溃。我只是想知道是否有任何其他方法可以确保套接字在未收到任何数据时超时,或者我是否在这里遗漏了任何内容。我已经阅读了很多博客和帖子,但其中大多数只是建议使用对我不起作用的 SO_TIMEOUT。

sotimeout not working in a multipart http post on android 2.1

【问题讨论】:

您的应用是否使用过较小的文件? 我已经尝试了 1 mb 的文件,但错误仍然存​​在。我猜对于较小的文件,您在文件上传之间更有可能断开连接,但这不是重点。我希望能够在发生网络故障时使我的应用程序健壮。 我遇到了同样的问题,除了我的上传大小相当小,大约只有几 kb。似乎触发该错误所需的只是让网络在我检查它是否启动之后但在我调用 execute() 之前关闭。 【参考方案1】:

我面临与您相同的问题,使用相同的用例。它发生在运行 android 2.3.6 但不是在 4.x 上使用相同设备的三星 Galaxy s2 上。不幸的是,这正是我的客户使用的设备,它在大约 10 台具有各种 Android 版本和构造函数的其他测试设备上运行良好......

我花了几个小时尝试使用 HttpUrlConnection 库而不是 Apache 的 HttpClient,但最终结果是相同的。 AndroidHttpClient 显示相同的行为。这让我觉得这听起来像是硬件实现或操作系统相关的问题......

我发现的唯一解决方法是将HttpClient.execute() 方法放在单独的线程中,并调用thread.join(timeout) 作为安全措施,以在出现任何问题时停止线程。缺点是当上传运行正常但时间超过超时时,请求被中断...

如果你在此期间发现了一些东西,如果你能分享它,我将不胜感激。

【讨论】:

【参考方案2】:

您是否正在创建自己的 ClientConnectionManager?查看source 的AndroidHttpClient.newInstance()。

他们创建一个新的 BasicHttpParams 对象并将其传递给 ThreadSafeClientConnectionManager 和 DefaultHttpClient 的构造函数。除了在构造函数中,我没有看到在 ClientConnectionManager 上设置参数的方法。

【讨论】:

是的,我正在扩展 DefaultHttpClient 以创建我自己的启用 SSL 的 HttpClient。扩展类覆盖 createClientConnectionManager(),并按照您的说明设置 HttpParams。我列出的代码能够正确设置连接超时,因为当我增加超时时间时,我必须等待直到引发异常的时间也相应增加。唯一的问题是,无论我尝试什么值,都不会引发套接字超时。

以上是关于Apache HttpClient 4.0 无法在 Android 上的套接字超时的主要内容,如果未能解决你的问题,请参考以下文章

HTTPClient模块的HttpGet和HttpPost

HTTPClient模块的HttpGet和HttpPost

httpclient 4.0 使用

.net 4.0 和 .net 4.5 中的 HttpClient 有啥区别

在Apache HttpClient上使用HTTPS代理

HttpClient 4.0的使用详解