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; }
}
这很有趣。当这种情况发生时,我会非常对完整的堆栈跟踪感兴趣,因为它会检查正确的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
。