0

私は protobuf-net を使用していくつかのオブジェクトをネットワーク経由で送信してきましたが、これまでのところすべてがうまく機能しています。ただし、モノで実行しているときに逆シリアル化に失敗するクラスの特定のインスタンス化に遭遇しました。まったく同じオブジェクトが、.net で正しく実行されて逆シリアル化されます。byte[]md5 サムをチェックすることにより、mono および .net で実行したときに、ワイヤ経由で受信したものとまったく同じであることを確認しました。これは、protobuf-net デシリアライゼーションに問題があることを示しています。を逆シリアル化するために使用しているコードは次のbyte[]とおりです。

using (MemoryStream ms = new MemoryStream(serializedByteArray)) 
{ 
    return (MyProtoBufDto)Serializer.Deserialize<MyProtoBufDto>(ms); 
}

ここに私が得ている例外があります:

System.IO.EndOfStreamException: Failed to read past end of stream.
at ProtoBuf.ProtoReader.Ensure (int,bool) <0x00167>
at ProtoBuf.ProtoReader.ReadString () <0x0005b>
at (wrapper dynamic-method) System.Collections.Generic.KeyValuePair`2<string, string>.proto_18 (object,ProtoBuf.ProtoReader) <0x000c8>
at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read (object,ProtoBuf.ProtoReader) <0x0002d>
at ProtoBuf.Meta.RuntimeTypeModel.Deserialize (int,object,ProtoBuf.ProtoReader) <0x00112>
at ProtoBuf.ProtoReader.ReadTypedObject (object,int,ProtoBuf.ProtoReader,System.Type) <0x00056>
at ProtoBuf.ProtoReader.ReadObject (object,int,ProtoBuf.ProtoReader) <0x0001b>
at (wrapper dynamic-method) System.Collections.Generic.KeyValuePair`2<string, System.Collections.Generic.List`1<System.Collections.Generic.KeyValuePair`2<string, string>>>.proto_16 (object,ProtoBuf.ProtoReader) <0x00220>
at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read (object,ProtoBuf.ProtoReader) <0x0002d>
at ProtoBuf.Meta.RuntimeTypeModel.Deserialize (int,object,ProtoBuf.ProtoReader) <0x00112>
at ProtoBuf.ProtoReader.ReadTypedObject (object,int,ProtoBuf.ProtoReader,System.Type) <0x00056>
at ProtoBuf.ProtoReader.ReadObject (object,int,ProtoBuf.ProtoReader) <0x0001b>
at (wrapper dynamic-method) MyGroupDto.proto_14 (object,ProtoBuf.ProtoReader) <0x001bc>
at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read (object,ProtoBuf.ProtoReader) <0x0002d>
at ProtoBuf.Meta.RuntimeTypeModel.Deserialize (int,object,ProtoBuf.ProtoReader) <0x00112>
at ProtoBuf.ProtoReader.ReadTypedObject (object,int,ProtoBuf.ProtoReader,System.Type) <0x00056>
at ProtoBuf.ProtoReader.ReadObject (object,int,ProtoBuf.ProtoReader) <0x0001b>
at (wrapper dynamic-method) System.Collections.Generic.KeyValuePair`2<MyGroupNameDto, MyGroupDto>.proto_12 (object,ProtoBuf.ProtoReader) <0x00197>
at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read (object,ProtoBuf.ProtoReader) <0x0002d>
at ProtoBuf.Meta.RuntimeTypeModel.Deserialize (int,object,ProtoBuf.ProtoReader) <0x00112>
at ProtoBuf.ProtoReader.ReadTypedObject (object,int,ProtoBuf.ProtoReader,System.Type) <0x00056>
at ProtoBuf.ProtoReader.ReadObject (object,int,ProtoBuf.ProtoReader) <0x0001b>
at (wrapper dynamic-method) MyResultProtoBufDto.proto_8 (object,ProtoBuf.ProtoReader) <0x002b9>
at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read (object,ProtoBuf.ProtoReader) <0x0002d>
at ProtoBuf.Meta.RuntimeTypeModel.Deserialize (int,object,ProtoBuf.ProtoReader) <0x00112>
at ProtoBuf.ProtoReader.ReadTypedObject (object,int,ProtoBuf.ProtoReader,System.Type) <0x00056>
at ProtoBuf.ProtoReader.ReadObject (object,int,ProtoBuf.ProtoReader) <0x0001b>
at (wrapper dynamic-method) MyProtoBufDto.proto_6 (object,ProtoBuf.ProtoReader) <0x00116>
at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read (object,ProtoBuf.ProtoReader) <0x0002d>
at ProtoBuf.Meta.RuntimeTypeModel.Deserialize (int,object,ProtoBuf.ProtoReader) <0x00112>
at ProtoBuf.Meta.TypeModel.DeserializeCore (ProtoBuf.ProtoReader,System.Type,object,bool) <0x0005b>
at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream,object,System.Type,ProtoBuf.SerializationContext) <0x00097>
at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream,object,System.Type) <0x0001f>
at ProtoBuf.Serializer.Deserialize<MyProtoBufDto> (System.IO.Stream) <0x00033>
at MyClient.Serialization.ProtoBufSerialization.DecompressAndDeserialize<MyProtoBufDto> (byte[]) <0x0008b>

mono 2.10.9 と最新の mono 3.2.3 を試しましたが、同じ例外が発生しました。最新の protobuf-net dll バージョン (2.0.0.666) を使用しています。protobuf-net-mono ディレクトリ (mono コンパイラでコンパイル?) と通常の .net コンパイル バージョンから dll を試しましたが、mono で実行するとこの例外が発生し続けます。

MyProtoBufDtoクラスの詳細:

[DataContract]
public class MyProtoBufDto
{
    [DataMember(Order = 1)]
    public List<MyResultProtoBufDto> Result { get; set; }
}

[DataContract]
public class MyResultProtoBufDto
{
    [DataMember(Order = 1)]
    public Dictionary<MyGroupNameDto, MyGroupDto> Groups { get; set; }
}

[DataContract]
public class MyGroupDto
{
    [DataMember(Order = 1)]
    public Dictionary<string, List<KeyValuePair<string, string>>> Group { get; set; }
}

MyGroupNameDtoただのenum

詳細情報: これは Linux で mono を使用しています。Windows でモノラルをまだテストしていません。ワイヤ オフの byte[] と解凍後の byte[] の両方が mono と Windows で同一であることを確認したため、protobuf-net にまったく同じデータを供給する必要があります。

更新 シリアル化されたオブジェクトから空のコレクションを常に削除するようにサーバー側に変更を加えました。それ以来、このエラーは発生していません。protobuf が空のコレクションと null コレクションを区別しないことは理解していますが、モノと .net で動作が異なり、このエラーが発生したことは依然として独特です。

4

3 に答える 3

1

それは興味深いです。聞いてもいいですか: mono on what ? Windowsのモノ?Linuxでモノ?私は再現を試みることができますが、私たちが同じものを見ていることを確認するためにあなたが私に与えることができるものは、本当に私を助けます. 実際、可能であれば、 「シリアライズしようとしているデータの base-64 がここにあります」(つまり、)が本当に役立つでしょう。あるいは、「これは、デシリアライズしない発明されたデータを生成するコードです」サンプルですか?serializedByteArray

エラーの意味を説明するには: 何かが「{n} バイトが必要」と宣言しました - この場合はReadString. これを内部バッファにロードしようとしますが、Stream十分なデータが得られません。

また、コール スタックについても少し心配しDecompressAndDeserializeています。もちろん、圧縮には何の問題もありませんが、「正しいデータを取得できましたか」というチェックを行っているときは、解凍するですか? または?1 つの可能性は、異なる結果を生成しているのは解凍レイヤーであるということです。

喜んで調査します。しかし、より多くのコンテキスト/サンプルを提供できれば、多くの時間を節約できます-公開サイトでそれができない場合は、電子メールなどで可能ですか?

于 2013-09-26T07:17:47.833 に答える
0

両方のエンドポイントが protobuf-net を使用して .NET 環境で実行されていますか、それとも一方が異なっていますか (例: C++ ライブラリを使用)?

ソケット経由で C++ アプリケーション (Linux) から送信されたメッセージを protobuf-net (Windows) を使用して逆シリアル化するときに、同じ問題に一度遭遇しました。

私のメッセージは次のようになりました。

message Envelope
{
  required int32 type = 1;  
  required bytes data = 2;  
}

C++ 側では、サイズを渡さずに「データ」(埋め込みメッセージ) を設定していました。

envelope->set_data(buf);

それ以外の

envelope->set_data(buf, bufSz);

これは、シリアル化されたメッセージのサイズが間違っている (envelope->ByteSize()) だけでなく、バ​​ッファーの末尾にゴミが含まれていることを意味していました。これがおそらく、protobuf-net がそれを余分なフィールドとして解釈し、必要以上に解析し続けた理由です。 .

それが同じ線に沿ったものであるかどうかを確認する価値があります。

于 2013-09-26T15:00:26.610 に答える