我在网络客户端/服务器应用程序中使用 protobuf-net。每个数据包都使用 BZip2Input/Output 流压缩以压缩我的消息。这已经好几个星期了,但是我最近修改了服务器的对象,并且得到了 BZip2Input 流不支持查找的异常(它不支持)。我想这是因为 protobuf 检测到它可以跳过某些字段,并尝试方便地这样做。
有没有办法禁用这种行为,并强制 protobuf-net 通过读取数据来跳过字段?(不求)。
更新:在下面添加了完整的堆栈跟踪。根据您的评论,该流的 CanSeek 回调中必须存在错误。你怎么看?
Server First Chance Exception: BZip2InputStream Seek n
ot supported Stack Trace: at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream.S
eek(Int64 offset, SeekOrigin origin)
Server_NewRequestReceived Exception: System.NotSupportedException: BZip2InputStream Seek not supported
at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream.Seek(Int64 offset, origin)
at ProtoBuf.ProtoReader.Seek(Stream source, Int32 count, Byte[] buffer)
at ProtoBuf.ProtoReader.SkipField()
at proto_2(Object, ProtoReader)
at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSeriali zer.Read(Object value, ProtoReader source)
at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, source)
at ProtoBuf.Meta.TypeModel.TryDeserializeAuxiliaryType(ProtoReader reader, format, Int32 tag, Type type, ref Object value, Boolean skipOtherFields, asListItem, Boolean autoCreate, Boolean insideList)
at ProtoBuf.Meta.TypeModel.TryDeserializeList(TypeModel model, ader, DataFormat format, Int32 tag, Type listType, Type itemType, ref Object value)
at ProtoBuf.Meta.TypeModel.TryDeserializeAuxiliaryType(ProtoReader reader, format, Int32 tag, Type type, ref Object value, Boolean skipOtherFields, asListItem, Boolean autoCreate, Boolean insideList)
at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader, Type type, value, Boolean noAutoCreate)
at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type, SerializationContext context)
at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type)
at ProtoBuf.Serializer.Deserialize(Stream source)
创建此类以解决 SharpZipLib 错误。
public class NonSeekableStreamWrapper : Stream
{
public Stream BaseStream { get; private set; }
public NonSeekableStreamWrapper(Stream baseStream)
{
BaseStream = baseStream;
}
public override void Flush()
{
BaseStream.Flush();
}
public override long Seek(long offset, SeekOrigin origin)
{
return BaseStream.Seek(offset, origin);
}
public override void SetLength(long value)
{
BaseStream.SetLength(value);
}
public override int Read(byte[] buffer, int offset, int count)
{
return BaseStream.Read(buffer, offset, count);
}
public override void Write(byte[] buffer, int offset, int count)
{
BaseStream.Write(buffer, offset, count);
}
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return false; }
}
public override long Length
{
get { return BaseStream.Length; }
}
public override long Position { get; set; }
}