C# Protobuf net:试图读取流的结尾

C# Protobuf net:试图读取流的结尾,c#,protobuf-net,C#,Protobuf Net,我们的系统在使用protobuf net序列化一条消息时,有时(但不是每次)会引发下面暴露的错误。错误的原因是什么?我如何减轻它 请注意,我们已经在使用反序列化WithLengthPrefix 更新: 相关代码在这里 private const PrefixStyle PrefixStyleInPlace = PrefixStyle.Fixed32; public static byte[] SerializeObjectToByteArray<TSerializable>(TSer

我们的系统在使用protobuf net序列化一条消息时,有时(但不是每次)会引发下面暴露的错误。错误的原因是什么?我如何减轻它

请注意,我们已经在使用
反序列化WithLengthPrefix

更新: 相关代码在这里

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;
    }
代码在这里

 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);
            }
        }
    }
内部抽象类SystemMessage:ISystemMessage,IEquatable
{
受保护的系统消息():此(Guid.NewGuid(),DateTime.UtcNow)
{
}
受保护的系统消息(Guid消息ID,DateTime createdTimeUtc)
{
MessageId=MessageId;
CreatedTimeUtc=新日期时间(CreatedTimeUtc.Ticks);//TODO:直到PROTOBUF-NET修复问题335
}
[原成员(1)]
公共Guid消息ID{get;private set;}
[原成员(2)]
public DateTime CreatedTimeUtc{get;private set;}
...
}
[协议(SkipConstructor=true)]
内部密封类TransportMessage:SystemMessage,ISystemMessage
{
//仅针对序列化程序,请在将来删除
私有传输消息()
{
}
公共传输消息(Guid收件人、总线消息数据)
:此(data.MessageId、data.CreatedTimeUtc、收件人、数据)
{
}
公共传输消息(Guid消息ID、DateTime createdTimeUtc、Guid收件人、总线消息数据)
:base(messageId,createdTimeUtc)
{
如果(data==null)抛出新的ArgumentNullException(“数据”);
if(recipient.IsEmpty())抛出新ArgumentException(“recipient不能是空值”);
收件人=收件人;
数据=数据;
}
[原成员(1)]
公共Guid收件人{get;private set;}
[原成员(2)]
公共消息数据{get;private set;}
}
[协议(SkipConstructor=true)]
内部密封类总线消息:SystemMessage、ISystemMessage、IEquatable
{
专用总线消息()
{
}
公共总线消息(Guid发布者、BizMessage数据)
:此(data.MessageId,data.CreatedTimeUtc,publisher,data)
{
}
公共总线消息(Guid messageId、DateTime createdTimeUtc、Guid发布者、BizMessage数据):基(messageId、createdTimeUtc)
{
如果(data==null)抛出新的ArgumentNullException(“数据”);
Publisher=Publisher;
数据=数据;
}
[原成员(1)]
公共Guid发布服务器{get;protected set;}
[原成员(2)]
公共BizMessage数据{get;protected set;}
}
[协议(SkipConstructor=true)]
内部密封类BizMessage:SystemMessage,IEquatable
{
私有字符串_jsonMessage;
私有对象_data=null;
公共BizMessage(对象数据):base()
{
如果(data==null)抛出新的ArgumentNullException(“数据”);
_数据=数据;
}
专用BizMessage(){}
来自JSON的公共静态BizMessage(字符串jsonData)
{
if(string.IsNullOrEmpty(jsonData))
抛出新ArgumentException();
返回新的BizMessage(){JsonMessage=jsonData};
}
[原成员(75)]
内部字符串JsonMessage
{
得到
{
if(string.IsNullOrEmpty(_jsonMessage))
{
如果(_data==null)
抛出新的ApplicationException(
“其中一个,_data或序列化的json消息必须有一个值”);
_jsonMessage=JsonSerializer.SerializeObjectToJson(_data);
}
返回jsonMessage;
}
私有集{u jsonMessage=value;}
}
公共类型MessageType
{
得到
{
更新数据();
如果(_data==null)
返回类型(无效);
返回_data.GetType();
}
}
公共对象原始数据
{
得到
{
更新数据();
返回数据;
}
}
私有void UpdateData()
{
如果(_data==null)
{
if(string.IsNullOrEmpty(_jsonMessage))
抛出新的ApplicationException(
“其中一个,_data或序列化的json消息必须有一个值”);
_data=JsonSerializer.DeserializeObjectFromJson(_jsonMessage);
}
}
}

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

当我使用套接字传输时,发生了此错误。我发现这是由于数据不完整造成的。

服务器向客户端发送1024字节的数据包长度,但客户端仅接收800字节。解析时出错。

我能看到您序列化/反序列化的代码吗?嗨,马克,我已经更新了票证。如果你还需要什么,请告诉我。谢谢,我已经用进行了测试,并且它成功地运行到完成(1000万次迭代):我真的很想帮忙,但是我很有限,因为我无法重现错误。该测试对您成功吗?您使用的是哪个版本的proto buf?我想知道您是否希望检查应用程序中的某个地方是否存在并发问题。在大多数情况下,如果流出现间歇性问题,是因为它们被并发访问,并且不是线程安全的,请详细说明“不完整数据”。你的答案很难回答。答案是肯定的
 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);
            }
        }
    }