1

ソケット経由でバイト配列を送信しています。送信されるデータは、次のバイト配列の長さを示す 4 バイトから始まります。

// get the amount of data being sent
byte[] lengthOfReplyAsArray = new byte[4];
forceRead(inputStream, lengthOfReplyAsArray);
int lengthOfReply = byteArrayToInt(lengthOfReplyAsArray);

// read the data into a byte array
byte[] reply = new byte[lengthOfReply];
forceRead(inputStream, reply);

InputStream からデータを読み取るために使用されるメソッド:

private byte[] forceRead(InputStream inputStream, byte[] result)
        throws IOException {

    int bytesRead = 0;
    int total = result.length;
    int remaining = total;

    while (remaining > 0)
        remaining -= inputStream.read(result, bytesRead, remaining);

    return result;

}

バイト配列を整数に変換するために使用されるメソッド:

private int byteArrayToInt(byte[] byteArray) {
    int result = 0;

    for (int i = 0; (i<byteArray.length) && (i<8); i++) {
        result |= (byteArray[3-i] & 0xff) << (i << 3);
    }
    return result;                  
}

問題は、データが到着順に読み取られないことです。最初の 4 バイトは正常に読み取られています。残りはごちゃまぜ。データがクライアントに正しく到着することを確認するために、TCP ダンプを作成しました。データが 4 つの TCP パケットに分割されているように見えます。InputStream は、最初のパケットの最初の 4 バイト、次に 4 番目のパケットのデータ全体、2 番目のパケットの最後の部分 (「最後のパケットの長さ」から始まる)、および 3 番目のパケットのデータ全体を返します。この順番で。

この問題の原因を知っている人はいますか?

4

1 に答える 1

2

バイト配列を読み取るためのロジックは正しくありません。

からドキュメントへ:

入力ストリームから最大 len バイトのデータをバイト配列に読み取ります。len バイトまで読み取ろうとしますが、それより少ない数が読み取られる可能性があります。実際に読み取られたバイト数は整数として返されます。

読み取られた最初のバイトは要素 b[off] に格納され、次のバイトは b[off+1] に格納されます。読み取られるバイト数は、最大で len に等しくなります。k を実際に読み取ったバイト数とします。これらのバイトは要素 b[off] から b[off+k-1] に格納され、要素 b[off+k] から b[off+len-1] は影響を受けません。

ただし、bytesRead変数はループ全体で 0 のままであるため、入力ストリームからのデータは常にバッファーの先頭に書き込まれ、既にそこにあるデータが上書きされます。

何がうまくいくか (-1 をチェックすると、ストリームが途中でデータremainingを使い果たして増加する場合に、残りから -1 を減算しないようになります。これは、バッファ オーバーランが発生するまでループが不必要に実行されることを意味します)remainingネガティブ):

while ((bytesRead = inputStream.read(result, total - remaining, remaining)) != -1
     && remaining > 0) {
    remaining -= bytesRead;
于 2012-04-26T08:25:32.187 に答える