2011-01-05 42 views
1

基本的に私はウェブページのHTMLコンテンツをダウンロードしようとしています。方法は非常に簡単です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メソッドを呼び出すときにハングすることを通知します。接続のreadtimeoutを設定しようとしましたが、動作しません。どのように私はSocketRead0のブロックを検出して取得することができますか?

編集:私が実際に持っている問題は、getReponseCodeがいくつかのgetInputStreamといくつかのread()メソッドを暗黙的に呼び出してから、readSocket0()でハングするということです。とにかく、getReponseCode()の呼び出しが安全であることを確認できますか? は、ここに1つのスレッド吊りのスタックトレースです:レベル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

このコードは、ダウンロードしたWebページを潜在的に改ざんする可能性があります。 InputStreamReaderを正しく設定するには、Webページの文字セットを使用する必要があります。 – jtahlborn

答えて

2

ソケット読み込みがブロック操作で最新の呼び出しです。それ以上のデータがあるか、ストリームの終わりに達したか、または接続が閉じられるまでブロックされます。

+2

ありがとうございます。 setReadTimeOut()が機能しない理由についても説明できますか?私のスレッドがハングアップするということは、さらに多くのデータがあり、まだストリームの終わりではないということです。 setReadTimeout()が最初にしか動作しないと言うのは事実ですか?つまり、タイムアウト期間内にread()の開始時に受け取ったデータがあればOKです。データがそれ以上受信されなくても、スレッドはそこでハングして待機します。そうですか? – altair211

2

readline関数を呼び出す前に、バッファにデータが読み込まれていることを確認する必要があります。 Peterが述べたように、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/HttpURLConnectionhtml –

1

メソッドprivate native int socketRead0(FileDescriptor fd, byte b[], int off, int len, int timeout) throws IOException がタイムアウト0(デフォルト)を取得した場合、タイムアウトは使用されません。したがって、IOExceptionをスローする代わりにブロックすることができます。

2

私もこのエラーがあり、解決しました。この問題は、ソフトウェアが応答を送信しないサーバーへの接続を開こうとするが、エラーも発生しないことがあるために発生します。

ソフトウェアはまだサーバーの応答を待っていますが、決して来ません。

これを避けるには、setConnectTimeout()メソッドを使用する必要があります。そのため、サーバーが決められた時間内に応答を送信しない場合、接続は中止されます。

setConnectTimeout() reference

関連する問題