C# &引用;源数据中的字段无效:0“;ProtoBuf网络和Compact框架出错

C# &引用;源数据中的字段无效:0“;ProtoBuf网络和Compact框架出错,c#,serialization,compact-framework,deserialization,protobuf-net,C#,Serialization,Compact Framework,Deserialization,Protobuf Net,在使用ProtoBuf Net在compact framework和完整的.Net framework之间进行序列化/反序列化时,有人注意到任何问题吗?我有一个名为LogData的类,我正在CompactFramework3.5下序列化该类,将其传输到服务器(运行.NETFramework4.0),然后服务器进行反序列化。有时它有效,有时它抛出上述错误,我还没有缩小到任何具体的原因。我用不同的值做了很多测试,似乎找不到任何押韵或错误发生的原因。我在下面包括我的类(减去各种构造函数)。我已经多次查

在使用ProtoBuf Net在compact framework和完整的.Net framework之间进行序列化/反序列化时,有人注意到任何问题吗?我有一个名为LogData的类,我正在CompactFramework3.5下序列化该类,将其传输到服务器(运行.NETFramework4.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<LogData>(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();
     }         
  }
private void writeLogDataServer(日志数据)
{
使用(var client=new TcpClient())
{
client.Connect(主机、SignalLineServerPort);
使用(var stream=client.GetStream())
{
使用(var ms=new MemoryStream())
{
序列化器。序列化(ms、数据);
var buffer=ms.GetBuffer();
int位置=0;
WriteFrameMarkers(流);
byte[]frameLengthBuffer=位转换器.GetBytes(buffer.Length);
stream.Write(frameLengthBuffer,0,IntByteSize);
while(位置<缓冲区长度)
{
int length=Math.Min(ChunkSize,buffer.length-position);
流写入(缓冲区、位置、长度);
位置+=块大小;
}
}
}
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<LogData>(ms);
           }
           return data;
        }
        catch (Exception ex)
        {
           Console.WriteLine(string.Format("Error occurred: {0}", ex.Message));
           return null;
        }
     }
     return null;
  }
public覆盖日志数据读取数据(NetworkStream)
{
if(stream.DataAvailable)
{
尝试
{
常量int chunkSize=250;
字节[]缓冲区=新字节[IntByteSize];
int messageSize=0;
int totalBytesRead=0;
日志数据;
使用(var ms=new MemoryStream())
{
如果(!ReadFrameMarkers(流))
返回null;
totalBytesRead=stream.Read(缓冲区,0,IntByteSize);
if(totalBytesRead!=IntByteSize)
返回null;
messageSize=BitConverter.ToInt32(缓冲区,0);
totalBytesRead=0;
while((totalBytesRead
简单一点:您可以使用:

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

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


一旦您删除了这些额外的不正确的零,我希望您会发现它是有效的。

我知道主开发人员@MarcGravel已经回答了,但我只想分享我自己的$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<LogData>(ms);
}
byte[]msg=新字节[4096];
int bytesRead=someStreamClass.Read(msg,04096);
使用(MemoryStream ms=新的MemoryStream(msg,0,字节读取))
{    
logData=序列化程序。反序列化(ms);
}

@马奎尔:谢谢你这个伟大的图书馆

我可以看一下您用来:序列化、发送到连线、从连线读取、反序列化的代码吗?我敢打赌你不小心在缓冲区中留下了一些0填充,而没有限制读取的长度。我编辑了这篇文章以包含序列化和反序列化代码。我省略了处理连接的协商验收等的接线代码。如果你需要更多关于代码的细节,请告诉我。非常感谢,马克。谢谢,马克,如果你在三州地区,我欠你一些饮料。有趣的是,简单的事情是最令人沮丧的。@WiredWiz你刚刚错过了我!我大约一周前在那里。但不是现在;P