【问题标题】:Protobuf-net: Attempted to read past the end of the streamProtobuf-net:尝试读取流的末尾
【发布时间】:2012-12-28 16:45:31
【问题描述】:

我们的系统在使用 protobuf-net 序列化一条消息时,有时但不是每次都会引发下面公开的错误。错误的原因是什么?如何缓解?

请注意我们已经在使用DeserializeWithLengthPrefix

更新: 相关代码在这里

private const PrefixStyle PrefixStyleInPlace = PrefixStyle.Fixed32;
public static byte[] SerializeObjectToByteArray<TSerializable>(TSerializable source) where TSerializable : class
    {
        byte[] result;
        using (var memoryStream = SerializeObjectToStream(source))
        {
            result = memoryStream.ToArray();
        }
        return result;
    }


    public static TResult DeserializeObject<TResult>(byte[] source)
    {
        TResult result;
        using (var memoryStream = new MemoryStream(source))
        {
            memoryStream.Position = 0;
            result = Serializer.DeserializeWithLengthPrefix<TResult>(memoryStream,PrefixStyleInPlace);
        }

        return result;
    }

    public static MemoryStream SerializeObjectToStream<TSerializable>(TSerializable source) where TSerializable : class
    {
        var memoryStream = new MemoryStream();

        Serializer.SerializeWithLengthPrefix(memoryStream, source,PrefixStyleInPlace);
        memoryStream.Position = 0;
        return memoryStream;
    }


    public static TResult DeserializeObject<TResult>(MemoryStream sourceStream)
    {
        TResult result;
        result = DeserializeObject<TResult>(sourceStream.ToArray());
        return result;
    }

留言

System.IO.EndOfStreamException : Attempted to read past the end of the
 stream.
 +++++++++++++++++++ STACK TRACE: at ProtoBuf.ProtoReader.Ensure(Int32 count, Boolean trict) in
 c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 234 at
 ProtoBuf.ProtoReader.ReadString() in
 c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 471 at
 proto_15(Object , ProtoReader ) at
 ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object
 value, ProtoReader source) in
 c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line
 49 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object
 value, ProtoReader source) in
 c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 721 at
 ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key,
 ProtoReader reader, Type type) in
 c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 556 at
 proto_16(Object , ProtoReader ) at
 ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object
 value, ProtoReader source) in
 c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line
 49 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object
 value, ProtoReader source) in
 c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 721 at
 ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key,
 ProtoReader reader, Type type) in
 c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 556 at
 proto_11(Object , ProtoReader ) at
 ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object
 value, ProtoReader source) in
 c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line
 49 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object
 value, ProtoReader source) in
 c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 721 at
 ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key,
 ProtoReader reader, Type type) in
 c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 556 at
 proto_16(Object , ProtoReader ) at
 ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object
 value, ProtoReader source) in
 c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line
 49 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object
 value, ProtoReader source) in
 c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 721 at
 ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key,
 ProtoReader reader, Type type) in
 c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 556 at
 proto_13(Object , ProtoReader ) at
ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object
 value, ProtoReader source) in
 c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line
 49 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object
 value, ProtoReader source) in
 c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 721 at
 ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key,
 ProtoReader reader, Type type) in
 c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 556 at
 proto_16(Object , ProtoReader ) at
 ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object
 value, ProtoReader source) in
 c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line
 49 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object
 value, ProtoReader source) in
 c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 721 at
 ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key,
 ProtoReader reader, Type type) in
 c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 556 at
 proto_2(Object , ProtoReader ) at
 ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object
 value, ProtoReader source) in
 c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs:line
 49 at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object
 value, ProtoReader source) in
 c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 721 at
 ProtoBuf.Meta.TypeModel.DeserializeWithLengthPrefix(Stream source,
 Object value, Type type, PrefixStyle style, Int32 expectedField,
 TypeResolver resolver, Int32& bytesRead, Boolean& haveObject,
 SerializationContext context) in
 c:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 351 at
 ProtoBuf.Serializer.DeserializeWithLengthPrefix[T](Stream source,
 PrefixStyle style, Int32 fieldNumber) in
 c:\Dev\protobuf-net\protobuf-net\Serializer.cs:line 303 at
 ProtoBuf.Serializer.DeserializeWithLengthPrefix[T](Stream source,
 PrefixStyle style) in
 c:\Dev\protobuf-net\protobuf-net\Serializer.cs:line 288 at
 ermeX.Common.ObjectSerializer.DeserializeObject[TResult](Byte[]
 source) in
    [ProtoContract(SkipConstructor = true)]
    [ProtoInclude(100, typeof(BusMessage))]
    [ProtoInclude(200, typeof(TransportMessage))]
    [ProtoInclude(300, typeof(BizMessage))]

代码在这里

 internal abstract class SystemMessage : ISystemMessage, IEquatable<SystemMessage>
    {
        protected SystemMessage():this(Guid.NewGuid(),DateTime.UtcNow)
        {
        }
        protected SystemMessage(Guid messageId,DateTime createdTimeUtc)
        {
            MessageId = messageId;
            CreatedTimeUtc = new DateTime(createdTimeUtc.Ticks);//TODO: UNTIL PROTOBUF-NET FIXES ISSUE 335 
        }

        [ProtoMember(1)]
        public Guid MessageId{get;private set;}

        [ProtoMember(2)]
        public DateTime CreatedTimeUtc { get; private set; }

        ...
    }


    [ProtoContract(SkipConstructor = true)]
    internal sealed class TransportMessage : SystemMessage, ISystemMessage<BusMessage>
    {
        //just for the serializer, remove in the future
        private TransportMessage()
        {
        }

        public TransportMessage(Guid recipient, BusMessage data)
            : this(data.MessageId, data.CreatedTimeUtc, recipient, data)
        {
        }

        public TransportMessage(Guid messageId, DateTime createdTimeUtc, Guid recipient, BusMessage data)
            : base(messageId, createdTimeUtc)
        {
            if (data == null) throw new ArgumentNullException("data");
            if (recipient.IsEmpty()) throw new ArgumentException("recipient cannot be an empty value");
            Recipient = recipient;
            Data = data;
        }

        [ProtoMember(1)]
        public Guid Recipient { get; private set; }

        [ProtoMember(2)]
        public BusMessage Data { get; private set; }
    }
    [ProtoContract(SkipConstructor = true)]
    internal sealed class BusMessage: SystemMessage, ISystemMessage<BizMessage>,IEquatable<BusMessage>
    {
        private BusMessage()
        {

        }
        public BusMessage(Guid publisher,BizMessage data)
            : this(data.MessageId,data.CreatedTimeUtc,publisher, data)
        {


        }

        public BusMessage(Guid messageId, DateTime createdTimeUtc, Guid publisher, BizMessage data) : base(messageId,createdTimeUtc)
        {
            if (data == null) throw new ArgumentNullException("data");
            Publisher = publisher;
            Data = data;
        }
        [ProtoMember(1)]
        public Guid Publisher { get; protected set; }

        [ProtoMember(2)]
        public BizMessage Data { get; protected set; }
    }

    [ProtoContract(SkipConstructor = true)]
    internal sealed class BizMessage : SystemMessage, IEquatable<BizMessage>
    {
        private string _jsonMessage;
        private object _data = null;

        public BizMessage(object data) : base()
        {
            if (data == null) throw new ArgumentNullException("data");
            _data = data;
        }

        private BizMessage(){}

        public static BizMessage FromJson(string jsonData)
        {
            if(string.IsNullOrEmpty(jsonData)) 
                throw new ArgumentException();
            return new BizMessage(){JsonMessage = jsonData};
        }

        [ProtoMember(75)]
        internal string JsonMessage
        {
            get
            {
                if(string.IsNullOrEmpty(_jsonMessage))
                {
                    if (_data == null)
                        throw new ApplicationException(
                            "One of both, _data or the serialized json message must have a value");
                    _jsonMessage = JsonSerializer.SerializeObjectToJson(_data);
                }
                return _jsonMessage;
            }
            private set { _jsonMessage = value; }
        }

        public Type MessageType
        {
            get
            {
                UpdateData();
                if (_data == null)
                    return typeof(void);
                return _data.GetType();
            }
        }

        public object RawData
        {
            get
            {
                UpdateData();
                return _data;
            }
        }

        private void UpdateData()
        {
            if (_data == null)
            {
                if (string.IsNullOrEmpty(_jsonMessage))
                    throw new ApplicationException(
                        "One of both, _data or the serialized json message must have a value");
                _data = JsonSerializer.DeserializeObjectFromJson<object>(_jsonMessage);
            }
        }
    }

【问题讨论】:

  • 我能看到你序列化/反序列化的代码吗?
  • 嗨,Marc,我已经更新了票证。需要帮助请叫我。谢谢
  • 我已经用this test 进行了测试,并且它成功运行到完成(10M 次迭代):我真的很想提供帮助,但我非常有限,因为我无法重现错误。该测试对您来说是否成功?
  • 您使用的是哪个版本的 proto-buf?
  • 我想知道您是否检查过您的应用程序中是否存在并发问题。在大多数情况下,当您遇到流的间歇性问题时,是因为它们正在被并发访问并且不是线程安全的

标签: c# protobuf-net


【解决方案1】:

当我指定要反序列化的“类型”与被序列化的原始类型不同时,我看到了这个错误。我想如果您的对象已更改并且您尝试反序列化与新版本不兼容的旧版本对象(即旧字节数组),也会发生这种情况。

【讨论】:

    【解决方案2】:

    当我使用socket传输时,出现了这个错误。我发现是数据不完整造成的。
    服务器向客户端发送长度为1024字节的数据包,但客户端只收到800字节。解析出错。

    【讨论】:

    • 请详细说明“不完整的数据”。你的答案非常稀缺。
    • 服务器向客户端发送长度为1024字节的数据包,但客户端只收到800字节。解析有错误
    猜你喜欢
    • 1970-01-01
    • 2013-08-02
    • 1970-01-01
    • 1970-01-01
    • 2014-09-09
    • 2015-05-11
    • 2020-12-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多