2013-10-28 18 views
5

私はシリアル化され、非直列化可能オブジェクトを持っていますが、逆シリアル化時に、それは私にエラーをスロー:なぜ私のprotobuf-netストリームは機能しませんか?

Invalid field in source data: 0

これは、直列化復元のための

コードが起こっている理由を私は知らないし、受信:シリアル化

public void listenUDP() 
{ 
     EndPoint ep = (EndPoint)groupEP; 
     //BinaryFormatter bf = new BinaryFormatter(); 
     recieving_socket.Bind(ep); 
     while (true) 
     { 

      byte[] objData = new byte[65535]; 
      recieving_socket.ReceiveFrom(objData, ref ep); 
      MemoryStream ms = new MemoryStream(); 
      ms.Write(objData, 0, objData.Length); 
      ms.Seek(0, SeekOrigin.Begin); 

      messageHandle(ProtoBuf.Serializer.Deserialize<SimplePacket>(ms)); 
      ms.Dispose(); 


     } 
    } 

コード:

public void sendDataUDP(Vec2f[] data) 
    { 

      SimplePacket packet = new SimplePacket(DateTime.UtcNow, data); 
      //IFormatter formatter = new BinaryFormatter(); 
      MemoryStream stream = new MemoryStream(); 
      System.Diagnostics.Stopwatch st = System.Diagnostics.Stopwatch.StartNew(); 
      //formatter.Serialize(stream, data); 
      ProtoBuf.Serializer.Serialize<SimplePacket>(stream, packet); 
      //Console.WriteLine(st.ElapsedTicks); 
      stream.Close(); 
      st.Restart(); 
      sending_socket.SendTo(stream.ToArray(), sending_end_point); 
      //Console.WriteLine(st.ElapsedTicks); 
      st.Stop(); 

    } 

答えて

6

いるProtobufメッセージのルートオブジェクトは、Googleの仕様で定義されたように、メッセージのの任意の概念を含んでいません。これは意図的なものなので、連結は2つのフラグメントをマージすることと同じです。その結果、消費コードはそれ自身を単一のメッセージに制限する必要があります。これは、すべてのprotobuf実装間で同一であり、protobuf-netに固有ではありません。

現在起こっていることは、あなたのバッファが現在大型で、最後にゴミが入っていることです。 現在、(1つのメッセージを読んでいるため)は、ガーベッジがすべて0になる可能性が高く、ゼロはフィールドに有効なマーカーではありません。しかし、バッファを再使用すると、ゴミは何かになる可能性があります。

あなたのケースでは、これを行う最も簡単な方法は、SerializeWithLengthPrefix/DeserializeWithLengthPrefixのメソッドを使用することです。これはメッセージの先頭にペイロードの長さを付加し、

最終的な考えとして、あなたのコードは、全体のメッセージを読んでいることを保証することは明らかではありません。単一の受信は(少なくともTCP上で)メッセージの一部を返すことができます - または2とビットメッセージなど:TCPはメッセージベースではなくストリームベースです。

関連する問題