2013-10-28 21 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的消息中的根對象,如由谷歌規範所定義,不包括該消息的的任何概念。這是有意的,所以連接和合並兩個片段是一樣的。因此,消費代碼需要將自身限制爲一條消息。這在所有protobuf實現之間是相同的,並且不特定於protobuf-net。

發生什麼事是你的緩衝區目前超大,最後是垃圾。 當前(因爲你正在閱讀一條消息)垃圾最可能是全零,零不是一個字段的有效標記。但是,當重新使用緩衝區時,垃圾可能......任何東西。

在你的情況下,可能最容易的方法是使用SerializeWithLengthPrefix/DeserializeWithLengthPrefix方法,它通過在消息的開頭預先輸入有效負載長度並僅處理那麼多數據來處理所有這些。

作爲最終的想法:我不清楚你的代碼會保證已經讀取了一個整個消息;一次接收可能(至少在TCP上)返回消息的一部分 - 或2和一個消息等:TCP是基於流的,而不是基於消息的。