Protobuf-net禁用寻求

时间:2013-06-20 20:55:26

标签: c# protobuf-net bzip2

我在网络客户端/服务器应用程序中使用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; }
    }

1 个答案:

答案 0 :(得分:2)

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

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

所以不,它目前没有这个选项,因为它信任流来说实话。当然,它可能只是我的错误,因此请求堆栈跟踪。

如果这是一个真正的“东西”,那么可能会添加这样一种机制。


编辑:是的,这是SharpZipLib中BZip2InputStream.cs的错误;它有:

    /// <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");
    }

所以,它可以从不寻求,但它声称如果 base 流可以。

它应该报告false而不是回显基本流CanSeek