c# Protobuf-net:如何从网络流中连续反序列化

本文关键字:连续 反序列化 网络 Protobuf-net | 更新日期: 2023-09-27 17:53:03

我(感激地)使用Marc Gravell的优秀的Protobuf-net协议缓冲区库。不幸的是,我很不聪明,很难理解对通过网络传入的对象进行反序列化的正确方法。

作为我努力的基础,我遵循这些问题中的建议:

使用protobuf-net发布反序列化(protocolBuffer)序列化数据
protobuf:连续序列化和反序列化到/从套接字

我正在保持TCP连接打开整个会话(分钟…)个小时……谁知道呢?),并且只要连接存在,就使用一个持续存在的网络流。我在这个流中收到了许多PB消息。

考虑到我正在使用"TryDeserializeWithLengthPrefix",我希望库能够在流上等待有足够的数据来解析整个对象。但情况似乎并非如此。

我写了一个简单的测试:
    [Test]
    public void DeserializeSimpleObjectInParts ()
    {
        SimpleObject origin = new SimpleObject();
        byte[] wholeObj = ProtobufSerializer.SerializeToByteArray ( origin );
        int length = wholeObj.Length;
        int midpoint = length / 2;
        int sizeA = midpoint;
        int sizeB = length - midpoint;
        byte[] aaa = new byte[sizeA];
        byte[] bbb = new byte[sizeB];
        for ( int i = 0; i < midpoint; i++ )
        {
            aaa [ i ] = wholeObj [ i ];
        }
        for ( int j = midpoint; j < length; j++ )
        {
            bbb [ j - midpoint ] = wholeObj [ j ];
        }
        using ( MemoryStream streamA = new MemoryStream ( aaa ) )
        {
            using ( MemoryStream streamB = new MemoryStream ( bbb ) )
            {
                streamA.Position = 0;
                streamB.Position = 0;
                Debug.LogDebug ( "streamA.Length = " + streamA.Length + ", streamB.Length = " + streamB.Length );
                object resultA = null;
                bool succeededA = false;
                try {
                    succeededA = ProtobufSerializer.Deserialize ( streamA, out resultA );
                }
                catch ( Exception e )
                {
                    Debug.LogDebug ( "Exception = " + e );
                    Debug.LogDebug ( "streamA.Position = " + streamA.Position + ", streamA.Length = " + streamA.Length );
                }
            }
        }
    }

请注意,在上面的"ProtobufSerializer。"反序列化"只是通过我自己的服务类直接调用"TryDeserializeWithLengthPrefix"。类型编码业务在那里。

当我运行这个测试时,抛出以下异常:

System.IO.EndOfStreamException: Failed to read past end of stream.

这个来自Google的朋友的建议是我有责任检查一下我的套接字代码中的长度前缀。但这有什么用呢?c#网络流没有长度属性供我比较。

我真的必须做一个中间步骤,在流上运行循环,构建正确大小的字节数组,然后从它们中生成我传递给Protobuf-net的新流吗?这似乎是一个反模式和性能的打击。

我在这里错过了什么?

c# Protobuf-net:如何从网络流中连续反序列化

考虑到我正在使用"TryDeserializeWithLengthPrefix",我希望库能够在流上等待足够的数据来解析整个对象。

在抽象流对象上没有可靠和有效的方法来"排序等待"。

c#网络流没有长度属性供我比较。

计算从套接字流写入缓冲区流的数据数。那将是你的"Length"属性用来与你在开始时得到的长度前缀进行比较。一旦有了足够的数据,将缓冲区流查找回前缀,并将其传递给反序列化器以获得对象。现在再次查找缓冲区流并重用它来获取下一条消息。重复。