0

私はこの非常に奇妙な問題と戦っています。誰かが理由を説明してくれることを願っています。

ソケット接続を介してファイルからデータを転送するためのこのコードがあります。

    byte[] chunk = new byte[Constants.TRANSFER_CHUNK_SIZE];
    try (InputStream fileInputStream = new FileInputStream(sourceFile); BufferedInputStream buffFileInputStream = new BufferedInputStream(fileInputStream)) {
        while (offset < sourceFileSize) {
            int numBytes = buffFileInputStream.read(chunk, 0, Constants.TRANSFER_CHUNK_SIZE);
            Message chunkMessage = new Message(MessageType.SPM_TRANSFER_CHUNK, numBytes, null, chunk);
            this.sendMessage(chunkMessage);
        }
    }

メソッド sendMessage は特別なことは何もしません。オブジェクトを ObjectOutputStream 経由で送信するだけです。

private void sendMessage(Message message) {
    try {
       this.conOutputStream.writeObject(message);
       this.conOutputStream.flush();
    } catch (IOException ex) {
            ......
    }
}

Message クラス自体は次のようになります。

public class Message implements Serializable {

protected final MessageType type;
protected final int intValue;
protected final String stringValue;
protected byte[] data;
protected final long longValue;

public Message(MessageType type, int intValue, long longValue, String stringValue, byte[] data) {
    this.type = type;
    this.intValue = intValue;
    this.stringValue = stringValue;
    this.data = data;
    this.longValue = longValue;
}

................

}

送信機側でチャンク配列を印刷すると、データは問題ありませんが、受信機側では常に最初のチャンクからデータを受信します (最初の 3 バイトのみが印刷されます)。

RC: 73 68 51
RC: 73 68 51
RC: 73 68 51
RC: 73 68 51
.......

私がすでに知っていること:

  • 問題は輸送中ではありません。
  • while サイクルのすべてのループで新しい配列を作成すると、この問題が解決されます (ただし、メモリが非効率的であるため、変更しました。)

前もって感謝します。

4

2 に答える 2

0

最後に、この問題の解決策を見つけました。この問題は、シリアライゼーション キャッシュが原因で発生します。ObjectOutputStream は、以前に同じストリームに送信した場合、同じオブジェクトを (変更されていても) 送信しません。

すべてのメッセージを送信する前にObjectOutputStreamをリセットすると、おそらくパフォーマンスが低下して問題が解決しましたが、問題は解決しました。これで、ObjectOutputStreamは常に新しいデータを送信します。

私の場合、メソッド sendMessage() を変更したので、メッセージ オブジェクトを送信する前にObjectOutputStreamをリセットするようになりました。

private void sendMessage(Message message) {
    try {
       this.conOutputStream.reset();
       this.conOutputStream.writeObject(message);
       this.conOutputStream.flush();
    } catch (IOException ex) {
            ......
    }
}
于 2013-04-16T08:43:11.440 に答える
0
public SyncPlaneMessage(MessageType type, int intValue, long longValue, String stringValue, byte[] data) {
    // ...
    this.data = data;
    // ...
}

渡された配列への参照を保存しています。コンストラクターの呼び出し後にその配列が変更された場合は、変更されますthis.data。これが、アレイのコピーを作成すると問題が解決する理由です。

配列をコピーするとより多くのメモリが使用されますが、どのような選択肢がありますか? コピーを作成する適切な場所は、少なくともコンストラクター内であり、whileループ内ではありません。

this.data = Arrays.copyOf(data, data.length);
于 2013-03-28T13:26:57.770 に答える