2013-10-28 8 views
5

Ich habe ein Objekt, das serialisiert werden kann und deserialisiert aber auf Deserialisierung wirft es mir einen Fehler:Warum funktioniert mein Protobuf-Net-Stream nicht?

Invalid field in source data: 0

Ich weiß nicht, warum dieser

Code für die Deserialisierung geschieht und Empfang:

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(); 


     } 
    } 

-Code für die Serialisierung:

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(); 

    } 

Antwort

6

das Root-Objekt in einer protobuf Nachricht, wie durch die Google-Spezifikation definiert ist, enthält keine Vorstellung von dem Ende der Nachricht. Dies ist beabsichtigt, so dass die Verkettung identisch ist mit dem Verschmelzen von zwei Fragmenten. Folglich muss sich der konsumierende Code auf eine einzelne Nachricht beschränken. Dies ist bei allen protobuf-Implementierungen identisch und nicht spezifisch für protobuf-net.

Was passiert ist, dass Ihr Puffer derzeit überdimensioniert ist, mit Müll am Ende. Derzeit (weil Sie eine Nachricht lesen), dass Müll höchstwahrscheinlich nur Nullen ist, und eine Null ist kein gültiger Marker für ein Feld. Bei der Wiederverwendung des Puffers könnte der Müll jedoch ... alles Mögliche sein.

In Ihrem Fall wahrscheinlich der einfachste Weg, dies zu tun ist, um die SerializeWithLengthPrefix/DeserializeWithLengthPrefix Methoden zu verwenden, die für Sie alle damit umgehen, indem die Nutzlastlänge am Anfang der Nachricht vorangestellt wird, und nur die Verarbeitung, die viele Daten.

Als abschließender Gedanke: es ist mir nicht klar, dass Ihr Code garantieren wird, hat eine gesamte Nachricht gelesen; ein einzelner Empfang könnte (zumindest auf TCP) einen Teil einer Nachricht zurückgeben - oder 2 und ein Bit Nachrichten usw.: TCP ist strombasiert, nicht nachrichtenbasiert.

Verwandte Themen