2011-01-05 4 views
1

В основном я пытаюсь загрузить HTML-содержимое веб-страницы. Метод очень простthread зависает в socketRead0 Java

 HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); 
     BufferReader in = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream())); 
     String line; 
     StringBuilder pageBuilder = new StringBuilder(); 
     while ((line = in.readLine()) != null) { 
      pageBuilder.append(line + "\n"); 
     } 

Но иногда программа просто висит. Я пытался отлаживать, и трассировка стека потоков сообщает мне, что она зависает при вызове метода SocketRead0. Я попытался установить время ожидания для подключения, но он не работает. Любые идеи о том, как я могу обнаружить и пройти через блок SocketRead0?

Редактировать: Похоже, что проблема, которую я действительно имею, заключается в том, что getReponseCode неявно вызывает некоторые методы getInputStream и некоторые методы read(), а затем зависает при readSocket0(). В любом случае, я могу убедиться, что вызов getReponseCode() будет безопасным? Вот трассировка стека один нити подвешивания: Level 0 это самый последний вызов

thread 24stacktrace 
     At 0level 
     at method socketRead0 
     at line -2 
     At 1level 
     at method read 
     at line 129 
     At 2level 
     at method fill 
     at line 218 
     At 3level 
     at method read1 
     at line 258 
     At 4level 
     at method read 
     at line 317 
     At 5level 
     at method parseHTTPHeader 
     at line 687 
     At 6level 
     at method parseHTTP 
     at line 632 
     At 7level 
     at method getInputStream 
     at line 1200 
     At 8level 
     at method getResponseCode 
     at line 379 
     At 9level 
     at method pushFinalRedirectedURL 
     at line 132 
     At 10level 
     at method process 
     at line 134 
     At 11level 
     at method run 
     at line 40 
+1

как примечание стороны, этот код будет потенциально искажать загруженный веб-страницы. вы должны использовать кодировку веб-страницы для правильной настройки InputStreamReader. – jtahlborn

ответ

2

гнездо для чтения является операция блокировки. Он будет блокироваться, пока не появится больше данных, конец потока достигнут или соединение будет закрыто.

+2

Спасибо за объяснение. Можете ли вы также объяснить, почему setReadTimeOut() не работает. Поскольку мой поток зависает, значит, есть еще больше данных, и это еще не конец потока. Верно ли говорить, что setReadTimeout() работает только в начале. Я имею в виду, если есть некоторые данные, полученные в начале read() в течение периода ожидания, тогда это нормально, и даже если больше нет данных, поток просто висит там и ждет. Это правильно ? – altair211

2

Вам необходимо убедиться, что в вашем буфере есть данные для чтения, прежде чем вы вызываете функцию readline. Как отметил Питер, SocketRead - это блокирующая функция, которая означает, что когда она называется, она будет сидеть и ждать, пока данные не будут помещены в поток.

Попробуйте это:

while (in.ready()) { 
    line = in.readLine(); 
    pageBuilder.append(line + "\n"); 
} 

Here ссылка на BufferedReader API.

+0

Спасибо russel, теперь у меня, похоже, проблема с getReponseCode(). Пожалуйста, см. Мое редактирование .. – altair211

+0

Это усекает файл (возможно, ничего), когда в данный момент нет данных. Это предотвратит блокировку, но, вероятно, также предотвратит загрузку файла. –

+0

@Peter Вы правы, его оригинальный код, похоже, сделал то же самое, поэтому я подумал, что это не проблема. @ User304462 Я не знаю ответа, единственное, что я могу предложить, это проверить api и посмотреть, поможет ли это. http://download.java.net/jdk7/docs/api/java/net/HttpURLConnection.html –

1

Просто дополнение к предыдущим ответам о чтения сокета является блокирование: если метод private native int socketRead0(FileDescriptor fd, byte b[], int off, int len, int timeout) throws IOException получает тайм-аут 0 (по умолчанию), не используется тайм-аут. Следовательно, он может блокировать, а не бросать исключение IOException.

2

У меня тоже есть эта ошибка и она была решена. Эта проблема возникает из-за того, что иногда программное обеспечение пытается открыть соединение с сервером, который не отправляет ответ, но также не дает ошибки.

Программное обеспечение все еще ожидает ответа сервера, но оно никогда не приходит.

Чтобы избежать этого, вам необходимо использовать метод setConnectTimeout(), поэтому, если сервер не отправляет ответ в определенное время, соединение будет прервано.

setConnectTimeout() reference