Как убить вызов BufferedInputStream .read () - PullRequest
3 голосов
/ 28 января 2012

Я работаю над написанием программы для загрузки очень больших файлов (~ 2 ГБ) с сервера. Я написал программу для возможности возобновления частично завершенных загрузок,

Чтобы смоделировать плохое подключение к Интернету, во время загрузки я вытаскивал сетевой шнур из маршрутизатора. К сожалению, это приводит к зависанию моей программы при следующем вызове: while((bytesRead = in.read(data)) > 0)

(где bytesRead - это int, in - это BufferedInputStream, созданный из HttpURLConnection, а данные - это байтовый массив).

Я пытался «прервать» вызов, вызвав in.close () в другом потоке, но это не действует до тех пор, пока не будет восстановлено интернет-соединение (в это время выдается исключение).

Есть ли какой-нибудь способ, которым я могу предотвратить разрыв программы из-за разорванного подключения к Интернету?

Ответы [ 3 ]

2 голосов
/ 28 января 2012

Единственный надежный способ, который я нашел, - создать экземпляр Socket как InterruptibleChannel и выполнить прерывание в зависшем потоке ввода-вывода.(Кстати, вам не нужно использовать асинхронные вызовы NIO с InterruptibleChannels, блокировка ввода-вывода работает нормально, у вас просто есть действительно хороший и унифицированный способ пиковых обменов)

Хотя, похоже, что URLConnection не позволяет вам подключить пользовательскую фабрику сокетов.

Возможно, вам следует изучить HttpClient от Apache.

РЕДАКТИРОВАТЬ

Вот как вы создаете Interruptible Socket.

import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.channels.SocketChannel;

final SocketAddress remoteAddr =
    new InetSocketAddress(
        serverAddress,
        servicePort
    );

final SocketChannel socketChannel = SocketChannel.open( );

socketChannel.connect( remoteAddr );

// Here java.io.Socket is obtained
Socket socket = socketChannel.socket( );

У меня нет примера HttpClient, но я знаю, что вы можете настроить инициализацию сокета.

1 голос
/ 28 января 2012

См. http://thushw.blogspot.com/2010/10/java-urlconnection-provides-no-fail.html код для решения этой ситуации

Отредактировано : на самом деле установка тайм-аута Socket (в миллисекундах) с помощью setSoTimeout (как предлагается в комментарии к ссылке из Joop Eggen), вероятно, лучше.

1 голос
/ 28 января 2012

У вас есть .setReadTimeout(int timeout) на вашем URLConnection?

- РЕДАКТИРОВАТЬ

См. Ответ @DNA для точного решения:

в коротких словах вы можетепорождает параллельный поток, который .disconnect() s URLConnection (после того, как ваш второй поток спит в течение timeout миллисекунд), таким образом вызывая IOException, который выведет вас из остановленного чтения.

...