ProtoBuf-Net和Compact Framework中的“源数据中的无效字段:0”错误

当使用ProtoBuf-Net在紧凑框架和完整的.Net框架之间进行序列化/反序列化时,是否有人知道任何问题? 我有一个名为LogData的类,我在紧凑框架3.5下进行序列化,传输到服务器(运行.Net framework 4.0),然后反序列化。 有时候它会起作用,有时会引发上述错误,我还没有将其缩小到任何特定原因。 我已经用不同的值做了很多测试,并且在发生错误时似乎找不到任何押韵或理由。 我在下面包括我的课程(减去各种构造函数)。 我已多次查看任一侧的字节缓冲区,但尚未发现通过线路从一侧传输到另一侧的数据存在差异。

[ProtoContract] public class LogData { [ProtoContract] public enum LogSeverity { [ProtoEnum(Name = "Information", Value = 0)] Information, [ProtoEnum(Name = "Warning", Value = 1)] Warning, [ProtoEnum(Name = "Error", Value = 2)] Error, [ProtoEnum(Name = "Critical", Value = 3)] Critical } [ProtoMember(1)] public string UserID { get; set; } [ProtoMember(2)] public string ComputerName { get; set; } [ProtoMember(3)] public ExceptionProxy Exception { get; set; } [ProtoMember(4)] public LogData.LogSeverity Severity { get; set; } [ProtoMember(5)] public string Source { get; set; } [ProtoMember(6)] public string Caption { get; set; } [ProtoMember(7)] public string Description { get; set; } [ProtoMember(8)] public DateTime TimeOfOccurrence { get; set; } [ProtoMember(9)] public Guid SessionID { get; set; } [ProtoMember(10)] public string MethodName { get; set; } [ProtoMember(11)] public string OSVersion { get; set; } [ProtoMember(12)] public string Category { get; set; } [ProtoMember(13)] public string Location { get; set; } } [ProtoContract] public class ExceptionProxy { [ProtoMember(1)] public Type ExceptionType { get; set; } [ProtoMember(2)] public string Message { get; set; } [ProtoMember(3)] public string StackTrace { get; set; } [ProtoMember(4)] public ExceptionProxy InnerException { get; set; } } 

这是我执行序列化和发送的代码

  private void WriteLogDataToServer(LogData data) { using (var client = new TcpClient()) { client.Connect(Host, SignalLineServerPort); using (var stream = client.GetStream()) { using (var ms = new MemoryStream()) { Serializer.Serialize(ms, data); var buffer = ms.GetBuffer(); int position = 0; WriteFrameMarkers(stream); byte[] frameLengthBuffer = BitConverter.GetBytes(buffer.Length); stream.Write(frameLengthBuffer, 0, IntByteSize); while (position < buffer.Length) { int length = Math.Min(ChunkSize, buffer.Length - position); stream.Write(buffer, position, length); position += ChunkSize; } } } client.Close(); } } 

这是读取服务器上数据的代码

  public override LogData ReadData(NetworkStream stream) { if (stream.DataAvailable) { try { const int chunkSize = 250; byte[] buffer = new byte[IntByteSize]; int messageSize = 0; int totalBytesRead = 0; LogData data; using (var ms = new MemoryStream()) { if (!ReadFrameMarkers(stream)) return null; totalBytesRead = stream.Read(buffer, 0, IntByteSize); if (totalBytesRead != IntByteSize) return null; messageSize = BitConverter.ToInt32(buffer, 0); totalBytesRead = 0; while ((totalBytesRead < messageSize)) { int bufferSize = Math.Min(chunkSize, messageSize - totalBytesRead); buffer = new byte[bufferSize]; int bytesRead = stream.Read(buffer, 0, bufferSize); if (bytesRead != 0) { totalBytesRead += bytesRead; ms.Write(buffer, 0, bytesRead); } } ms.Seek(0, SeekOrigin.Begin); data = Serializer.Deserialize(ms); } return data; } catch (Exception ex) { Console.WriteLine(string.Format("Error occurred: {0}", ex.Message)); return null; } } return null; } 

简单一个:您使用:

 var buffer = ms.GetBuffer(); 

然后是buffer.Length 。 这意味着您使用的是超大的填充缓冲区。 如果你这样做,你需要使用ms.Length ,它会告诉你实际的长度。 或者,可以使用ms.ToArray() ,但这涉及额外的副本。

我的建议:继续使用GetBuffer(),但只写ms.Length字节,而不是buffer.Length字节。

一旦你删除了这些额外的错误零,我希望你会发现它有效。

我意识到主要的开发人员@MarcGravell已经回答了,但我只是想分享我自己的0.02美元来帮助我解决这个问题。 如果我有一个固定大小的byte []并获得一个读取的字节数,我可以在MemoryStream声明中指定它并解决问题。 此外,因为它适用于OP,所以在您完成阅读之前不要声明MemoryStream。

 byte[] msg = new byte[4096]; int bytesRead = someStreamClass.Read(msg, 0, 4096); using (MemoryStream ms = new MemoryStream(msg, 0, bytesRead)) { logData = Serializer.Deserialize(ms); } 

@MarcGravell:感谢这个伟大的图书馆!