6

Google プロトコル バッファを使用して、エンコードするすべてのメッセージの最大サイズを設定できますか?

エンコードするデータが X バイトを超えることがないことがわかっている場合、Google Protobuffs は常にサイズ Y のバッファを生成し、データ量が少ない場合はサイズ Y にパディングしますか?

4

1 に答える 1

5

プロトコル バッファのワイヤ形式では、これは簡単ではありません。これを行う方法はわかりませんが、1 つのオプションは、独自の長さヘッダーを使用してバッファーにシリアル化し、必要に応じて余分なデータを埋め込むことです

これはデフォルトでは追加されないため、長さの接頭辞を追加する必要があります。そうしないと、バッファの最後でゴミが読み取られます。末尾の 0 でさえ正当ではありません (フィールド番号を探していることになります)。

C++ または Jon の C# バージョンについてコメントすることはできませんが、私のC# バージョン (protobuf-net) では、次のようなことができるはずです (未テスト):

using(var  ms = new MemoryStream(fixedLength)) {
     ms.SetLength(fixedLength);
     Serializer.SerializeWithLengthPrefix(ms, obj);
     if(ms.Length > fixedLength) { /* boom */ }
     byte[] arr = ms.ToArray(); // use this
}

も使用している場合、これは正常に逆シリアル化する必要がありDeserializeWithLengthPrefixます。


再質問(コメント); protobuf-netSerializeWithLengthPrefix固有のメソッドです。C++版には何かあるかもしれませんが、かなりシンプルです。これをゼロから実装する最も簡単な方法は次のとおりです。

  • 実際のデータの量を示すために、固定長 (4 バイト) のヘッダーを残すと仮定します。
  • 4 バイトをスキップする (または 00-00-00-00 を書き込む)
  • 残りのバッファにシリアライズする
  • 書き込んだバイト数を調べる
  • その値をバッファの先頭に書き戻す

逆に、明らかに:

  • 4 バイトを読み取り、int として解釈する
  • データと同じくらいデシリアライズする

protobuf-net では、さらにいくつかのオプション (int をエンコードする方法、およびこれをラップして全体を 100% 値の protobuf ストリームとして処理できるようにするかどうか) を提供するため、もう少し複雑です。 - 特に、固定幅エンコーディングと「フィールド 0」を使用するように要求した場合の動作を説明したと思われます)。SerializeWithLengthPrefix

于 2010-05-12T08:22:37.547 に答える