У меня есть апплет Java, который использует класс HTTPURLConnection
для загрузки очень больших файлов на веб-сервер IIS-7. Апплет разбивает файлы на куски, а затем отправляет их с помощью потоковой передачи фиксированной длины в PHP-скрипт.
Иногда при загрузке фрагментов файлов сетевое соединение между клиентом и сервером загадочным образом обрывается. Когда это происходит, мой вызов метода writeBytes()
выдает IOException
, который я перехватываю. Перехватив это исключение, я опускаюсь в свой блок finally
, где пытаюсь все навести порядок. Поскольку в соединение было записано недостаточно данных (помните, что это потоковая передача фиксированной длины), попытка закрыть выходной поток также не удалась. В результате соединение, по-видимому, остается открытым (т. е. базовый сокет остается открытым). Кажется, это подтверждается просмотром исходный код метода close()
для класса StreamingOutputStream (обратите внимание на комментарий о том, что сокет не может быть закрыт).
Вопрос:
Есть ли изящный способ, которым я могу закрыться после того, как поймал 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 МБ, а возвращается код состояния 200. Сбой затем проявляется через 10 минут после последней успешной передачи с бесполезной ошибкой 500 (и обратите внимание, что это была только частичная передача; передано всего ~ 15 МБ). На самом деле это загадочное отключение происходит примерно через 1 минуту после начала всей процедуры, поэтому сообщения об истечении времени ожидания, которые я вижу в своих журналах трассировки IIS, являются отвлекающим маневром. Я не вижу ничего полезного в своих журналах PHP, журнале HTTPERR или системном журнале на сервере.