2

C# でシリアライズし、ZMQ を使用してネットワーク経由で送信したオブジェクトを C++ でデシリアライズする際に問題があります。C++ サーバー アプリケーション (Linux) が C# (Windows) からシリアル化されたメッセージを正常に受信し、メッセージを正常に逆シリアル化できる Windows に送り返すため、ZMQ 部分が正しく動作していると確信しています。その点で、あらゆる種類の切り捨てられたパケットまたはドロップされたパケットが発生しています。

ただし、Linux サーバーでメッセージを受信すると、C++ のデシリアライズ メソッドは正しくデシリアライズされず、一連のバイナリ データが 6 番目のフィールドにスローされます (これは MyObject.DebugString() で確認できます)。その他のフィールド。ただし、ここで奇妙なのは、5 つのフィールドを持つクラスが完全に正常に機能することです。C++ はそれを正しく逆シリアル化し、すべてのデータが正しく機能しています。以下は、私のコードのほんの一部です。どんな助けでも大歓迎です。

C#:
    MemoryStream stream = new MemoryStream();
    ProtoBuf.Serializer.Serialize<TestType>(stream, (TestType)data);
    _publisher.Send(stream.ToArray());

C++:
    message_t data;
    int64_t recv_more;
    size_t recv_more_sz = sizeof(recv_more);
    TestType t;
    bool isProcessing = true;
    while(isProcessing)
    {
      pSubscriber->recv(&data, 0);
      t.ParseFromArray((void*)(data.data()),sizeof(t));
      cout<<"Debug: "<<t.DebugString()<<endl;  

      pSubscriber->getsockopt(ZMQ_RCVMORE, &recv_more, &recv_more_sz);
      isProcessing = recv_more;
    }

出力は次のようになります。

Debug: f: "4\000\000\000\000\000\"

コピーと貼り付けに問題がありますが、出力はおそらく 3 ~ 4 行分続きます。

これは私の TestType クラス (プロト ファイル) です。

package Base_Types;

enum Enumr {
  Dog = 0;
  Cat = 1;
  Fish = 2;
}

message TestType {
  required double a = 1;
  required Enumr b = 2;
  required string c = 3;
  required string d = 4;
  required double e = 5;
  required bytes f = 6;
  required string g = 7;
  required string h = 8;
  required string i = 9;
  required string j = 10;
}

フィールド「f」がバイトとしてリストされているのは、UTF-8 エンコーディングに関する警告が表示される前に文字列だった場合、このクラスが 5 つのフィールド (列挙型はそれらの 1 つ) のみで動作する場合、それは与えられなかったからです。私にそのエラー。これは、逆シリアル化する代わりに、クラス全体のバイナリをフィールド "f" (フィールド 6) に投入するようなものです。

解決策: メモリがスレッド ソケットに送信される前にコピーされないという問題が発生しました。パブリッシャーが返送したとき、データをパッケージ化し、ルーターが受信したものを変更していました。内部で使用するデータを送信するには、C++ 側に memcpy() が必要です。助けてくれてありがとう。

4

1 に答える 1

0

私はそれをv2のリーダーで解析しましたが、完全に理にかなっているようです:

1=5
2=0
3=
4=yo
5=6
6=2 bytes, 68-69
7=how
8=are
9=you
10=sir

純粋に 16 進データから (.proto を使用せずに)行ったが、元のデータに近いはずであることに注意してください。しかし、最も注目に値するのは、それが無傷であるように見えることです。

だから:最初にすること。C++ 側で取得したバイナリが、送信したバイナリとまったく同じであることを確認します。途中で翻訳を行う場合、これは二重に重要です (たとえば、バイナリ => 文字列 - base-64 経由で行う必要があります)。

第二のこと; それでもうまくいかない場合は、C++ の実装に問題がある可能性があります。それはGoogleのペットの1つであるため、ありそうにないように思えますが、不可能なことは何もありません. バイナリが無傷であるにもかかわらず、奇妙な動作が続く場合は、C++ の担当者と話をして、うちの 1 人がカッコウになったかどうかを確認できます。

于 2011-06-24T22:32:26.863 に答える