捕获异常时如何优雅地清理HTTPURLConnection?

时间:2012-02-01 00:44:58

标签: java exception-handling applet httpurlconnection

我有一个Java applet,它使用HTTPURLConnection类将非常大的文件上传到IIS-7 Web服务器。 applet将文件分块,然后使用固定长度的流式传输到PHP脚本。

有时,在上传文件块时,客户端和服务器之间的网络连接会神秘地丢失。发生这种情况时,我对writeBytes()方法的调用会抛出IOException,我会抓住它。在捕获此异常后,我会进入finally块,在那里我尝试清理它。由于没有足够的数据写入连接(请记住,这是固定长度的流式传输),关闭输出流的尝试也会失败。结果,连接看起来“粘住”(即底层插座保持打开)。这似乎是通过查看StreamingOutputStream类的source codeclose()方法来验证的(注意说明无法关闭套接字的注释)。

问题:

在写出IOException的同时,抓住HTTPURLConnection之后我可以关闭一个优雅的方式吗?将HTTPURLConnection对象告诉disconnect()似乎不够好。

其他信息:

这是我通过调用writeBytes()类的HTTPURLConnection方法调用网络时看到的第一个异常:

java.io.IOException: Error writing request body to server
    at sun.net.www.protocol.http.HttpURLConnection$StreamingOutputStream.checkError(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection$StreamingOutputStream.write(Unknown Source)
    at java.io.DataOutputStream.write(Unknown Source)
    at MultiPartPostThread.run(MultiPartPostThread.java:321)

我捕获此异常,然后尝试关闭我用来写入连接的DataOutputStream对象。当我这样做时,我得到了这个例外:

java.io.IOException: insufficient data written
    at sun.net.www.protocol.http.HttpURLConnection$StreamingOutputStream.close(Unknown Source)
    at java.io.FilterOutputStream.close(Unknown Source)
    at MultiPartPostThread.run(MultiPartPostThread.java:370)

我可以通过注意在IIS日志中显示失败条目需要10分钟来验证套接字是否保持打开状态。延迟(10分钟)恰好是我的连接超时值。 IIS日志中的示例行(为简洁而修剪):

2012-01-31 20:20:07 POST /upload_handler.php 200 0 0 356 26215490 3666
2012-01-31 20:20:10 POST /upload_handler.php 200 0 0 356 26215490 3853
2012-01-31 20:30:22 POST /upload_handler.php 500 0 64 0 15286099 611442

请注意,在日志的前两行中我们正在很好地传输:每次发送25 MB,并返回200状态代码。然后失败然后在最后一次成功转移后10分钟出现,并且有一个无用的错误500(并注意这只是部分转移;仅转移了约15MB)。实际上,这个神秘的断开发生在整个过程大约1分钟,所以我在IIS跟踪日志中看到的超时消息是红色鲱鱼。我在PHP日志,HTTPERR日志或服务器上的系统日志中看不到任何帮助。

2 个答案:

答案 0 :(得分:1)

在您的信息流上呼叫close()应释放

使用的资源
HTTPURLConnection 

这是来自HTTPURLConnection javadoc的注释

在请求之后调用HttpURLConnection的InputStream或OutputStream上的close()方法可以释放与此实例关联的网络资源,但不会影响任何共享持久连接。如果此时持久连接处于空闲状态,则调用disconnect()方法可能会关闭底层套接字。

答案 1 :(得分:1)

我越是关注这一点,我越相信不能进行优雅的清理。 disconnect()调用似乎不足以关闭底层套接字;你只需等待它超时。

我想我会尝试使用Apache HttpComponents HttpClient(根据terrific SO wiki post底部的建议),看看它内置的错误处理是否可以解决这个奇怪的情况我是看到。

相关问题