如何使用 PrefixStyle 和 ProtoBuf-net 获取长度数?

DrG*_*one 4 c# protocol-buffers protobuf-net

在下面的示例中,如何使用 PrefixStyle 和 ProtoBuf-net 获取长度数?

PrefixStyle.Base128 和 PrefixStyle.Fixed32 有什么区别?

谢谢!

            PerfTest clone;
            using (MemoryStream ms = new MemoryStream())
            {
                Serializer.SerializeWithLengthPrefix(ms, obj,PrefixStyle.Base128);
                byte[] raw = ms.ToArray();
                ms.Position = 0;
                clone = Serializer.DeserializeWithLengthPrefix<PerfTest>(ms,PrefixStyle.Base128);

            }
Run Code Online (Sandbox Code Playgroud)

编辑:使用字节数组下方的代码长度为 22。为什么 TryReadLengthPrefix 返回 21?肯定是应该返回22?

           PerfTest clone;
            using (MemoryStream ms = new MemoryStream())
            {
                Serializer.SerializeWithLengthPrefix(ms, obj,PrefixStyle.Base128);
                byte[] raw = ms.ToArray();
                ms.Position = 0;

                int bArrayLen = ms.ToArray().Length; //returns 22

                int len;// set to 21. Why not 22?
                Serializer.TryReadLengthPrefix(ms, PrefixStyle.Base128,out len);

                clone = Serializer.DeserializeWithLengthPrefix<PerfTest>(ms,PrefixStyle.Fixed32);

            }
Run Code Online (Sandbox Code Playgroud)

Mar*_*ell 5

Fixed32 总是使用 4 个字节作为长度前缀 - 这对于手动打包消息的人来说似乎并不少见(实际上,由于重复请求,我什至不得不在某些时候添加不同的字节序版本)。

首选应该是 Base128,它使用“varint”编码,所以小数字需要更少的空间来编码。此外,此前缀样式可用于使一系列对象与具有字段的单个对象兼容repeated,这具有一些有用的应用。

重新获取长度;如果您正在使用DeserializeWithLenghPrefixDeserializeItems 您不需要- 它会在内部处理它。但如果你需要这个,看看Serializer.TryReadLengthPrefix.

澄清:这些*WithLengthPrefix方法的目的是允许在单个流中分离不同的对象/消息 - 最常见的是:网络套接字。这是必要的,因为协议本身假设整个流是单个消息,因此会一直尝试读取,直到流/套接字关闭。

重新 22 对 21 字节;那是因为长度前缀本身需要一些长度 :) 实际上如果数组是 22 我有点惊讶有效负载不是 20 - I 字节字段为首(使组合流本身成为有效的 protobuf 流),1 字节长度和 20 字节的有效载荷。我目前正在使用手机,因此无法运行示例进行调查;不过,可以省略字段头(可选) - 所以它可能是 1 字节长度,21 字节有效载荷。我稍后再看。