【发布时间】:2012-02-23 17:52:17
【问题描述】:
我有一个 Java 小程序,它使用 HTTPURLConnection 类将非常大的文件上传到 IIS-7 网络服务器。小程序将文件分块,然后使用固定长度流将这些片段发布到 PHP 脚本。
有时,在上传文件块时,客户端和服务器之间的网络连接会莫名其妙地断开。发生这种情况时,我对 writeBytes() 方法的调用会引发我捕获的 IOException。捕捉到这个异常后,我进入我的finally 块,在那里我尝试清理东西。由于写入连接的数据不足(请记住,这是固定长度的流式传输),关闭输出流的尝试也会失败。结果,连接似乎“保持不变”(即底层套接字保持打开状态)。这似乎可以通过查看 StreamingOutputStream 类的 source code 到 close() 方法来验证(注意说明套接字无法关闭的注释)。
问题:
在写到HTTPURLConnection 时,有没有一种优雅的方式可以在捕获IOException 后关闭?将HTTPURLConnection 对象告诉disconnect() 似乎还不够好。
附加信息:
这是我在调用HTTPURLConnection 类的writeBytes() 方法时引发的第一个异常:
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 日志或服务器上的系统日志中看不到任何有用的信息。
【问题讨论】:
标签: java exception-handling applet httpurlconnection