0

ローカルの桟橋でクライアントとサーブレットを実行しています。クライアントでメッセージを読むときは、次のようにします。

in = new Scanner(conn.getInputStream());
StringBuffer messageBuffer = new StringBuffer();
while (in.hasNext()) {
   messageBuffer.append(in.next()).append(" ");
}

サーブレットからのデータがない場合、サーブレットはフリーズするはずです

while (in.hasNext())

代わりに、空の messageBuffer になってしまい、それを処理して、メッセージを受け取るまでメソッドを何度も呼び出す必要があります。なぜこうなった?while ステートメントで停止して、データが入ってくるまで待つにはどうすればよいですか?

URL接続が開始される方法は次のとおりです(クライアントコンストラクターで1回):

try {
        url = new URL("http://localhost:8182/stream");
        conn = (HttpURLConnection) url.openConnection();
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException ioE) {
        ioE.printStackTrace();
    }
4

4 に答える 4

1

スキャナーのドキュメントから:

next() メソッドと hasNext() メソッド、およびそれらのプリミティブ型のコンパニオン メソッド (nextInt() や hasNextInt() など) は、最初に区切り文字パターンに一致する入力をスキップしてから、次のトークンを返そうとします。hasNext メソッドと next メソッドの両方が、さらなる入力を待つことをブロックする場合があります。hasNext メソッドがブロックするかどうかは、関連する next メソッドがブロックするかどうかとは関係ありません。

ブロックする可能性があると書かれていますが、API の一部ではありません。スキャンする内容に応じて、下線の実装に依存します。

とにかく、次のような方法で待機を自分で実装する必要があります。

while (!in.hasNext() && !stop){
   sleep();
}
于 2012-08-18T20:38:27.323 に答える
1

javadocには、ブロックされる可能性がScanner.hasNext()あると記載されています。それは本当に基礎となる に依存します。個人的には、ソケットから読み取るために a を使用することはありません。Scanner.next() InputStreamScanner

InputStreamReaderより健全なアプローチは、おそらく a でラップされたan を使用することBufferedReaderです。また、言及する価値があるのは、スレッドセーフが必要でない限り、StringBuilderではなくを使用する必要があることです。StringBuffer

BufferedReader br = 
    new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String input = null;
while ((input = br.readLine()) != null)
{
    sb.append(input).append(" ");
}

これは、readLine()受け取っているものに応じて、ニーズに合う場合と合わない場合があることを使用していることに注意してください。また、送信が完了すると、接続のもう一方の端が閉じられることも想定しています。read()代わりにいずれかのメソッドを使用して、それに応じて解析することをお勧めします。

以下のコメントから編集して追加します。これは文字通り、Java でブロック読み取りが機能する方法です。完全な例を次に示します。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class App 
{
    public static void main( String[] args ) throws MalformedURLException, IOException
    {
        URL url = new URL("http://www.google.com");

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        BufferedReader br = 
            new BufferedReader(new InputStreamReader(conn.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String input = null;
        while ((input = br.readLine()) != null)
        {
            sb.append(input).append(" ");
        }

        System.out.println(sb.toString());

    }
}

出力 (ここでは簡潔にするために省略していますが、ページ全体です):

<!doctype html><html itemscope="itemscope" itemtype="http://schema.org/WebPage"><head> ...
于 2012-08-18T20:46:45.793 に答える
0

私の経験では、私は常にブロッキングを回避しようとしてきたため、hasNext() に Scanner メソッドを使用することを避けてきました。

代わりに、InputStream を使用しました。コードで使用した InputStream:

conn.getInputStream();

その後、InputStream メソッドavailable()を使用して、情報が通過したかどうかを確認できます。

したがって、あなたのコードについては、次のことをお勧めします。

InputStream inStream = conn.getInputStream();
in = new Scanner(inStream);    
StringBuffer messageBuffer = new StringBuffer();    
while (in.available() <= 0)
{   
 try{
    Thread.sleep(100);
}
catch(InterruptedException e){}
}
messageBuffer.append(in.next()).append(" ");
于 2012-08-18T22:50:25.777 に答える
0

編集:

while ループの代わりに for ループを使用してみてください。範囲は 0 から (長さ -1) です。while(in.hasNextLine()) を使用して長さを見つけ、その中に長さカウンターを配置する必要があります。試してみてください。それはうまくいくはずです。

于 2012-08-18T20:35:23.900 に答える