mono下的protobuf net反序列化System.IO.EndOfStreamException

mono下的protobuf net反序列化System.IO.EndOfStreamException,mono,deserialization,protobuf-net,Mono,Deserialization,Protobuf Net,我一直在使用protobuf网络通过网络发送一些对象,到目前为止,一切都很顺利。然而,我遇到了我的类的一个特殊实例化,在mono下运行时无法反序列化。完全相同的对象反序列化在.net下正确运行。我已经通过检查md5总和,验证了在mono和.net下运行时,通过线路接收到的数据与在.net下运行时接收到的数据完全相同。这表明protobuf网络反序列化肯定存在问题。下面是我用来反序列化字节[]的代码: using (MemoryStream ms = new MemoryStream(serial

我一直在使用protobuf网络通过网络发送一些对象,到目前为止,一切都很顺利。然而,我遇到了我的类的一个特殊实例化,在mono下运行时无法反序列化。完全相同的对象反序列化在.net下正确运行。我已经通过检查md5总和,验证了在mono和.net下运行时,通过线路接收到的数据与在.net下运行时接收到的数据完全相同。这表明protobuf网络反序列化肯定存在问题。下面是我用来反序列化
字节[]
的代码:

using (MemoryStream ms = new MemoryStream(serializedByteArray)) 
{ 
    return (MyProtoBufDto)Serializer.Deserialize<MyProtoBufDto>(ms); 
}
MyGroupNameDto
只是一个
enum

更多信息: 这是在linux上使用mono。我还没有在windows上测试mono。我在mono和windows上验证了离线的字节[]和解压后的字节[]是相同的,因此我们应该向protobuf net提供相同的精确数据

更新
我们在服务器端做了一个更改,总是从序列化的对象中删除空集合,从那时起就没有遇到此错误。我知道protobuf没有区分空集合和空集合,但奇怪的是,mono和.net上的行为有所不同,它触发了这个错误。

这很有趣。我可以问一下:单声道对什么?windows上的mono?linux上的mono?我可以试着重新编程,但你能给我的任何东西都能确保我们看到的是同一件事,这对我真的很有帮助。实际上,如果可能的话,真正有帮助的是“这是我试图反序列化的数据的base-64”(即,
serializedByteArray
),这将允许我非常快速地确定是数据还是反序列化器出了错。或者,可能是一些“这里有一些代码生成一些虚构的数据,然后不会反序列化”示例

解释错误的含义:有东西声明“我需要{n}字节”——在本例中为
ReadString
。它试图将其加载到内部缓冲区,而
没有为其提供足够的数据

我还对调用堆栈中的
解压缩和反序列化
有点担心:当然,压缩没有任何问题-但是当您进行“我们是否获得了正确的数据”检查时,是在您解压缩之前吗?还是之后?一种可能是减压层产生了不同的结果


乐于调查;但如果你能提供更多的上下文/样本,那么这将节省很多时间——如果不能在公共站点上完成,那么可能通过电子邮件等?

< P>都是在.NET环境中使用ToBufff网络运行的,或者是它们中的一个不同(例如使用C++库)?

<>我曾经使用过从C++应用程序(Linux)通过套接字发送的原Buffnet网(Windows)反序列化消息时遇到过同样的问题。 我的消息如下所示:

message Envelope
{
  required int32 type = 1;  
  required bytes data = 2;  
}
在C++方面,我在不传递大小的情况下设置“数据”(嵌入消息),即

envelope->set_data(buf);
而不是

envelope->set_data(buf, bufSz);
这意味着不仅序列化消息的大小错误(信封->字节大小()),而且缓冲区的末尾还包含垃圾,这可能就是protobuf net将其解释为额外字段并继续解析超出其应解析的内容的原因


值得检查一下是否有相同的问题。

我能够找出这个奇怪问题的原因。显然,我最初调试这个问题时出错了。在.net和mono环境下运行时,我认为我发送用于反序列化的字节[]是相同的。然而,情况并非如此,错误在于将DeflateStream与反序列化结合使用。在mono下运行时,DeflateStream没有返回protobuf net所期望的所有字节

断开的代码如下所示:

using (MemoryStream ms = new MemoryStream(compressedByteArray))
using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress, true))
     return (MyProtoBufDto)Serializer.Deserialize<MyProtoBufDto>(ds);
using (MemoryStream msDecompressed = new MemoryStream())
{
     using (MemoryStream ms = new MemoryStream(compressedByteArray))
     using (DeflateStream ds = new DeflateStream(ms , CompressionMode.Decompress, true))
           ds.CopyTo(msDecompressed);

     msDecompressed.Seek(0, SeekOrigin.Begin);
     return (MyProtoBufDto)Serializer.Deserialize<MyProtoBufDto>(msDecompressed);
}
使用(MemoryStream ms=新的MemoryStream(compressedByteArray))
使用(DeflateStream ds=新的DeflateStream(ms,压缩模式。解压缩,真))
返回(MyProtoBufDto)序列化程序。反序列化(ds);
工作代码如下所示:

using (MemoryStream ms = new MemoryStream(compressedByteArray))
using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress, true))
     return (MyProtoBufDto)Serializer.Deserialize<MyProtoBufDto>(ds);
using (MemoryStream msDecompressed = new MemoryStream())
{
     using (MemoryStream ms = new MemoryStream(compressedByteArray))
     using (DeflateStream ds = new DeflateStream(ms , CompressionMode.Decompress, true))
           ds.CopyTo(msDecompressed);

     msDecompressed.Seek(0, SeekOrigin.Begin);
     return (MyProtoBufDto)Serializer.Deserialize<MyProtoBufDto>(msDecompressed);
}
使用(MemoryStream msDecompressed=new MemoryStream())
{
使用(MemoryStream ms=新的MemoryStream(compressedByteArray))
使用(DeflateStream ds=新的DeflateStream(ms,压缩模式。解压缩,真))
ds.CopyTo(msDecompressed);
msDecompressed.Seek(0,SeekOrigin.Begin);
return(MyProtoBufDto)序列化程序。反序列化(msDecompressed);
}

mono和.net之间存在这种差异,这太糟糕了。我知道DeflateStream使用底层缓冲区。Mono可能正在使用延迟实现,即即使请求更多字节,也只返回缓冲区中的解压缩字节。只要DeflateStream.ReadBytes返回至少1个字节,从技术上讲,这可能不会破坏任何.net规范。如果对protobuf net进行更改,在无法获得预期的数量时继续从流中读取字节,则可能会解决此问题。只有当ReadBytes返回零字节时,protobuf net才会抛出我们看到的异常

谢谢你的快速回复,马克。我用更多的信息更新了我的问题。我应该能在接下来的几天内把字节[]给你。嗨,马克。我们在服务器端做了一个更改,总是从序列化的对象中删除空集合,从那时起,我就无法重现这个错误。有趣的是,mono和.net上的行为有所不同。很抱歉,我无法提供字节[]供您进行故障排除。序列化始终在.net上。我在linux下的.net和mono上测试过反序列化。只有mono有这个问题。在反序列化之前,我已经验证了mono和windows上的实际字节[]是相同的,所以我认为这不是