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()
数を実際に返す(つまり、まだバッファに送信されていないデータ) ?
それとも、読み取りをブロックし続け、メッセージをキュー/リスト/ベクター/アレイリスト/その他にプッシュするスレッドを開始する方が実際には良い考えでしょうか? (同期が必要です)
私のアプリケーションはリアルタイムである必要があります (せいぜいミリ秒単位の遅延は、娯楽プログラムとしては基本的に許容されます)。プログラムはほとんど不完全なので、まだ試すことができません。