2

構造体をバイトストリームにシリアル化しています。私の方法は単純です。すべてのintをリトルエンディアンの順序でパックし、nullターミネータを含む文字列をコピーします。反対側は、バイトストリームを解凍する方法を静的に知っている必要があり、追加のメタデータはありません。

私の問題は、NULLポインタの処理方法がわからないということです。

ストリームに追加のメタデータがないため、何かを送信する必要があります。

私は次の2つのオプションを検討しました。

  1. '\ 0'を送信し、受信側にそれをNULLとして解釈させます。

  2. '\ 0'を送信し、受信側に'\ 0'として解釈させます(1バイトを割り当てます)

  3. char * str == NULLを表す特殊文字を送信します(例:ETX、EOT、EM?)

どう思いますか?

4

4 に答える 4

4

現在、特殊文字を渡して、シリアル化された文字列の最後に到達したことを受信側に伝えようとしているようです。これであなたを台無しにすることができる百万のケースがあります:

構造体にその特殊文字と等しいバイトが含まれている場合はどうなりますか。別の特殊文字でエスケープします。構造体に、エスケープ文字の後に特殊文字が続くバイトシーケンスが含まれている場合は、それも確認してください。

ええ、それは実行可能ですが、それはあまり良い解決策ではないと思います。エスケープ文字を探すためにパーサーを作成する必要があります。その後、コードを見る人は、何が起こっているのかを理解するために2時間を費やします。 。

(tl; dr)代わりに...シリアル化された文字列の最初の32ビットを文字列のバイト数と等しくするだけです。これは、シリアル化ごとに4バイトしかかからず、すべての問題を解決します。パーサーを記述したり、特殊文字について心配したりする必要はなく、コードを読み通す次の人にとって非常に簡単になります。

編集

JeremyPのおかげで、私はあなたの質問に本当に答えていないことに気づきました。すべての文字列に対してこれらの人の1人を送ってください:

struct s_str {bool is_null; intサイズ; char * str; };

nullの場合は、is_nullをtrueに設定するだけで、他の2つについて心配する必要はありません。サイズがゼロの場合は、is_nullをfalseに設定し、サイズをゼロに設定します。strに「\0」だけが含まれている場合は、is_nullをfalseに、サイズを1に、str[0]を「\0」に設定します。

私の意見では、これは最もメモリ効率の良い方法ではないかもしれませんが(おそらくどこかでバイトを節約できます)、あなたがしていることは間違いなく非常に明確です。

于 2012-04-05T10:27:50.983 に答える
2

こんなことしないで。長さを格納し、データ文字列と連結するために、いくつかの余分なバイトを使用します。受信側は長さをチェックして、ローカルバッファにどれだけ読み込む必要があるかを知ることができます。

于 2012-04-05T10:35:27.887 に答える
2

それはあなたのプロトコルにおけるポインタの重要性に依存します。ポインタが重要である場合、つまり受信者が構造体を再構築する方法を知っている必要がある場合は、何かを送信する必要があります。存在を示す0/非ゼロのバイト、またはポインターが指すバイト数を示す整数のいずれかです。

例:struct Foo {int * arr、char * text}

Struct Fooは、次のようにシリアル化できます。

<arr length><  arr   ><text length>< text >
  4 bytes    n bytes    4 bytes     n bytes
于 2012-04-05T10:40:23.233 に答える
2

シリアル化には既存のライブラリを使用することをお勧めします。現時点では2つ考えられます:tplとgwlibのgwser

についてtpl

tplを使用して、Cデータをすばやく簡単に保存および再ロードできます。Tplは、ファイル、メモリバッファ、およびファイル記述子を処理するため、ファイル形式、IPCメッセージ形式、またはデータの保存と取得が必要なシナリオとしての使用に適しています。

についてgwlibは、リンクを参照してください。あまり冗長ではありませんが、いくつかの使用例が示されています。

于 2012-04-05T10:46:50.173 に答える