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

Jon*_*hop 6 java applet exception-handling httpurlconnection

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

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

题:

有一种优雅的方式,我可以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)
Run Code Online (Sandbox Code Playgroud)

我捕获此异常,然后尝试关闭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)
Run Code Online (Sandbox Code Playgroud)

我可以通过注意在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
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*hop 1

我越深入地研究这个问题,就越确信无法进行优雅的清理。一次disconnect()调用似乎不足以关闭底层套接字;您只需等待它超时。

我想我会尝试使用Apache HttpComponents HttpClient (正如这篇很棒的 SO wiki 文章底部所推荐的那样),看看它的内置错误处理是否可以处理我所看到的这种奇怪的情况。