4

私の質問はこの投稿に似ています。しかし、最後に 0 バイトではなく、パケット長を送信しません。 Java で TCP ストリームを読み込む最も効率的な方法

だから、どうやってそれをコード化するのだろうと思っています。

現時点では私はちょうど使用します

this.socketIn = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
String line = this.socketIn.readLine();

パケットをスパム送信している間にパケットが送信された場合、まだ到着していないパケットを完全に読み取られた行としてカウントしますが、それは不完全であり、プロトコル全体を台無しにします。

私のプロトコルでは、各パケットは 0 バイト (0x00) で終了し、パケットがマージ/スタックされた場合に単一のパケットの終了を決定します。

だから私が実際にやろうとしているのは、パケットが完全に作成され、処理の準備ができていることを示すために 0x00 に到達するまでソケット ストリームを読み続けることです。特定の時間枠で0バイトで終了していないため、パケットはジャンクです。たとえば、5秒です。

どうすればこれを行うことができますか?

PS>私はNIOフレームワークを使用していませんが、接続ソケットごとに通常のスレッドを使用しています。更新を処理し、特定の更新をランダムユーザーに送信する完全に異なるグローバルスレッドでデータを注入することは非常に難しいため、NIOに切り替えたくありません(放送されません)。

これが私がこれまでに試したことです。

    String line = "";
    int read;
    long timeOut = System.currentTimeMillis();
    while(true) {
        read = this.socketIn.read();
        if (read == -1 || read == 0 || (System.currentTimeMillis()-timeOut) > 5000)
            break;
        line += read
    }
4

3 に答える 3

6

「遅いクライアント/サービス拒否」シナリオに対処するために setSocketTimeout を使用したスケッチを次に示します。

this.socket.setSoTimeout(5000);
BufferedReader br = new BufferedReader(
    new InputStreamReader(this.socket.getInputStream()));
StringBuilder sb = new StringBuilder();
try {
    int ch ;
    while ((ch == br.read()) != -1) {
        if (ch == 0) {
            String message = sb.toString();
            // process message
            sb.setLength(0);
        } else {
            sb.append((char) ch);
        }
    }
} catch (InterruptedIOException ex) {
    System.err.println("timeout!"); 
    ...
} finally {
    br.close();
}

socket.close()読み取りスレッドがデータを取得していないことを検出した場合にソケットオブジェクトを呼び出す2番目のスレッドを作成することにより、(残忍な) ソケットタイムアウトを実装することも可能だと思います。しかし、より単純なアプローチを考えると、それは重量級のsetSoTimeout()アプローチです。

于 2010-08-16T23:25:10.783 に答える
2
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
BufferedReader in = new BufferedReader(isr);
String line = "";
String response = "";
while ((line = in.readLine()) != null) {
    System.out.println(line);
    response = response + line + "\n";
    if (in.ready() == false) {
        break;
    }
}

その秘訣は、BufferedReader に属する ready 関数です。ループから抜け出すだけでなく、準備ができているかどうかを確認する必要があります。

于 2012-08-17T10:57:00.673 に答える
0

StringBuilder を使用する必要がありますか? または、EJP が書いたように自分でビルドします。どちらが速いですか?

            String line = "";
            int read;
            //long timeOut = System.currentTimeMillis();
            this.socket.setSoTimeout(5000);
            while(this.socket.isConnected()) {
            read = this.socketIn.read();
            if (read == -1)
                throw new IOException("Insufficient data / timeout)");
            else if(read == 0)
                break;
            line += (char)(read & 0xFF);
            }
于 2010-08-17T00:37:21.287 に答える