Protobuf-net禁用搜索

本文关键字:搜索 Protobuf-net | 更新日期: 2023-09-27 18:19:12

我在网络客户端/服务器应用程序中使用protobuf-net。每个数据包都用BZip2Input/Output流压缩,以压缩我的消息。这已经工作了几个星期了,但是我最近修改了服务器的对象,并且得到了一个异常,BZip2Input流不支持查找(它不支持)。我想这是因为protobuf检测到它可以跳过一些字段,并试图方便地这样做。

是否有一种方法可以禁用此行为,并通过读取数据强制protobuf-net跳过字段?(不是寻求)。

更新:在下面添加了完整的堆栈跟踪。根据你的评论,流一定有一个bug在它的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; }
    }

Protobuf-net禁用搜索

这很有趣。当这种情况发生时,我会非常对完整的堆栈跟踪感兴趣,因为它会检查正确的api,例如(来自ProtoReader.Seek)。

if (source.CanSeek)
{
    source.Seek(count, SeekOrigin.Current);
    // ...
}
else
{
    // ... does it the hard way, even if that means a Read loop
}

所以不,它目前没有这个选项,因为它相信流会告诉真相。当然,这可能只是我的错误,因此请求堆栈跟踪。

如果这是一个真正的"东西",可能会添加这样一个机制。


编辑:是的,这是一个bug在BZip2InputStream.cs在SharpZipLib;它有:

    /// <summary>
    /// Gets a value indicating whether the current stream supports seeking.
    /// </summary>
    public override bool CanSeek {
        get {
            return baseStream.CanSeek;
        }
    }

还有:

    /// <summary>
    /// Set the streams position.  This operation is not supported and will throw a NotSupportedException
    /// </summary>
    /// <param name="offset">A byte offset relative to the <paramref name="origin"/> parameter.</param>
    /// <param name="origin">A value of type <see cref="SeekOrigin"/> indicating the reference point used to obtain the new position.</param>
    /// <returns>The new position of the stream.</returns>
    /// <exception cref="NotSupportedException">Any access</exception>
    public override long Seek(long offset, SeekOrigin origin)
    {
        throw new NotSupportedException("BZip2InputStream Seek not supported");
    }

所以,它可以永远不能 seek,但它声称如果流可以,它就可以。

它应该报告false,而不是响应基流的CanSeek