"源数据中无效的字段:0"误差protobuf网和精简框架 [英] "Invalid field in source data: 0" error with ProtoBuf-Net and Compact Framework

查看:236
本文介绍了"源数据中无效的字段:0"误差protobuf网和精简框架的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是任何人都知道使用protobuf网连载/紧凑框架和完整的.NET框架之间的反序列化时的任何问题?我有一个类叫做LogData,我Compact Framework的3.5序列下,传输到服务器(运行.NET Framework 4.0),然后反序列化。有时工作,有时它抛出了上面的错误,我还没有将它缩小到任何具体原因。我做了很多很多的测试与不同的价值观和似乎无法找到任何情由时出现错误。我包括我下面的类(减去各种构造函数)。我已经看过上在多个场合两边的字节缓冲器而还没有找到在数据中的差被发送通过线路从一侧到另一



  [ProtoContract] 
公共类LogData
{

[ProtoContract]
公共枚举LogSeverity
{
〔ProtoEnum(NAME =信息,值= 0)
信息,
[ProtoEnum(名称=警告,值= 1)]
警告,
[ ProtoEnum(NAME =错误,值= 2)
错误,
[ProtoEnum(名称=严重,值= 3)
严重
}

〔ProtoMember(1)]
公共字符串用户名{获得;组; }
[ProtoMember(2)]
公共字符串计算机名{获得;组; }
[ProtoMember(3)]
公共ExceptionProxy异常{搞定;组; }
[ProtoMember(4)]
公共LogData.LogSeverity严重性{搞定;组; }
[ProtoMember(5)]
公共字符串来源{搞定;组; }
[ProtoMember(6)]
公共字符串字幕{搞定;组; }
[ProtoMember(7)]
公共字符串描述{搞定;组; }
[ProtoMember(8)]
公众的DateTime TimeOfOccurrence {搞定;组; }
[ProtoMember(9)]
公众的Guid的SessionID {搞定;组; }
[ProtoMember(10)]
公共字符串方法名{获得;组; }
[ProtoMember(11)]
公共字符串OSVERSION {搞定;组; }
[ProtoMember(12)]
公共字符串等级{搞定;组; }
[ProtoMember(13)]
公共字符串位置{搞定;组; }
}

[ProtoContract]
公共类ExceptionProxy
{

[ProtoMember(1)]
公共类型ExceptionType {搞定;组; }
[ProtoMember(2)]
公共字符串消息{搞定;组; }
[ProtoMember(3)]
公共字符串堆栈跟踪{搞定;组; }
[ProtoMember(4)]
公共ExceptionProxy的InnerException {搞定;组; }

}

下面是我的代码,做序列化和发送

 私人无效WriteLogDataToServer(LogData数据)
{
b $ b {
client.Connect(主机,SignalLineServerPort);使用(VAR流= client.GetStream())
{
使用
(VAR毫秒=新的MemoryStream())
{
Serializer.Serialize< LogData>(毫秒,数据);
VAR缓冲= ms.GetBuffer();
INT位置= 0;
WriteFrameMarkers(流);
字节[] = frameLengthBuffer BitConverter.GetBytes(buffer.Length);
stream.Write(frameLengthBuffer,0,IntByteSize);
,而(仓位< buffer.Length)
{
INT长度= Math.Min(CHUNKSIZE,buffer.Length - 位);
stream.Write(缓冲,位置,长度);
位置+ = CHUNKSIZE;
}
}
}
client.Close();
}
}



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

 公众覆盖LogData READDATA(的NetworkStream流)
{
如果(stream.DataAvailable)
{

{
const int的CHUNKSIZE = 250;
字节[]缓冲区=新的字节[IntByteSize]
INT MESSAGESIZE = 0;
INT totalBytesRead = 0;
LogData数据;
使用(VAR毫秒=新的MemoryStream())
{
如果
返回NULL(ReadFrameMarkers(流)!);
totalBytesRead = stream.Read(缓冲液,0,IntByteSize);
如果(totalBytesRead = IntByteSize!)
返回NULL;
MESSAGESIZE = BitConverter.ToInt32(缓冲液,0);
totalBytesRead = 0;
,而((totalBytesRead< MESSAGESIZE))
{
INT缓冲区大小= Math.Min(CHUNKSIZE,MESSAGESIZE - totalBytesRead);
缓冲区=新的字节[缓冲区大小]
INT读取动作= stream.Read(缓冲液,0,缓冲区大小);
如果(读取动作!= 0)
{
totalBytesRead + =读取动作;
ms.Write(缓冲液,0,读取动作);
}
}
ms.Seek(0,SeekOrigin.Begin);
数据= Serializer.Deserialize< LogData>(毫秒);
}
返回数据;
}
赶上(异常前)
{
Console.WriteLine(的String.Format(发生错误:{0},ex.Message));
返回NULL;
}
}
返回NULL;
}


解决方案

轻松一:您使用:

  VAR缓冲= ms.GetBuffer(); 



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



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



一旦你已经删除了这些额外的不正确的零,我想你会发现它工作原理。


Is anyone aware of any issues when using ProtoBuf-Net to serialize/deserialize between compact framework and the full .Net framework? I have a class called LogData that I am serializing under compact framework 3.5, transmitting to a server (running .Net framework 4.0), which then deserializes. Sometimes it works and sometimes it throws the above error and I have yet to narrow it down to any specific cause. I've done many many tests with different values and can't seem to find any rhyme or reason to when the error occurs. I'm including my classes below (minus the various constructors). I have looked at the byte buffer on either side on multiple occasions and have yet to find a difference in the data being sent over the wire from one side to the other.

[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; }

}

Here is my code that does the serialization and sending

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

And this is the code that reads the data on the server

  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;
  }

解决方案

Easy one: you use:

var buffer = ms.GetBuffer();

And then buffer.Length. That means you are using the oversized, padded buffer. If you do that you need to use ms.Length, which will tell you the actual length. Alternatively, ms.ToArray() may be used, but that involves an extra copy.

My advice: keep using GetBuffer(), but only write ms.Length bytes, not buffer.Length bytes.

Once you have removed these extra incorrect zeros, I expect you'll find it works.

这篇关于&QUOT;源数据中无效的字段:0&QUOT;误差protobuf网和精简框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆