У меня есть 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 или в системном журнале на сервере.