1

BufferedInputStream istreamからのストリームにラップされたからデータを受け取りたいですSocket。データには、最初にバイトn(8 ビットの符号なし整数) が含まれ、次にn実際のメッセージ (文字列ではなくバイナリ形式) を含むバイトが含まれます。だから私は次のコードを書きました(テストされていません):

public byte[] getNextMessageBytes() throws IOException {
    // Make sure the "length" byte is ready to be read
    if (this.istream.available() < 1) {
        return null;
    }

    // Peek 1 byte
    this.istream.mark(1);
    int length = this.istream.read();

    // -1 == EOF
    if (length < 0) {
        throw new EOFException();
    }

    // reset the marked byte
    this.istream.reset();

    // If all bytes available...
    // NOTE the 'length' byte is still in the stream
    if (this.istream.available() > length) {

        // Peek the bytes...
        this.istream.mark(length + 1);
        // Skips the 'length' byte
        this.istream.skip(1);

        byte[] data = new byte[length];
        int recv = this.istream.read(data, 0, length);
        if (recv == length) {
            this.istream.mark(0);
            return data;
        }
        // -1 == EOF
        if (recv < 0) {
            throw new EOFException();
        }
        this.istream.reset();
    }
    return null;
}

このコードは、基本的に最初に長さnバイトを読み取ります。次に、istream.available()使用可能な完全な長さが示されている場合、特定のバイト数を読み取ろうとし、成功した場合はバイト配列を返します。

ドキュメントBufferedInputStream.available():

この入力ストリームのメソッドの次の呼び出しによってブロックされることなく、この入力ストリームから読み取る (またはスキップする) ことができる推定バイト数を返します。次の呼び出しは、同じスレッドまたは別のスレッドである可能性があります。このバイト数の 1 回の読み取りまたはスキップはブロックされませんが、より少ないバイト数の読み取りまたはスキップが行われる可能性があります。

「ブロックせずに読み取ることができるバイト」は、「ソケットによって既に受信されたバイト」と解釈できますか? すでに受信したデータよりも少ないistream.available()数を実際に返す(つまり、まだバッファに送信されていないデータ) ?

それとも、読み取りをブロックし続け、メッセージをキュー/リスト/ベクター/アレイリスト/その他にプッシュするスレッドを開始する方が実際には良い考えでしょうか? (同期が必要です)

私のアプリケーションはリアルタイムである必要があります (せいぜいミリ秒単位の遅延は、娯楽プログラムとしては基本的に許容されます)。プログラムはほとんど不完全なので、まだ試すことができません。

4

1 に答える 1

0

「ブロックせずに読み取ることができるバイト」は、「ソケットによって既に受信されたバイト」と解釈できますか?

そう解釈するしかない。

istream.available() は実際に、既に受信したデータ (つまり、まだバッファに送信されていないデータ) よりも少ない数を返しますか?

保留中のデータであっても、ゼロから上に向かって何でも返すことができます。SSLSockets では、常にゼロを返します。

ただし、それを呼び出す必要はなく、複雑なコードも必要ありません。ブロッキングモードでストリームを読み取り、複数のスレッドを使用するだけです。

于 2013-01-31T23:13:46.813 に答える