解码节俭对象这些额外的字节是什么?
Decoding Thrift Object what are these extra bytes?
我正在编写一个不依赖于 thrift 定义的纯 JS thrift 解码器。我一直在关注这个方便的指南,它是我过去几天的圣经:https://erikvanoosten.github.io/thrift-missing-specification/
我的解析器几乎可以正常工作了,但是有一个字符串类型给程序带来了麻烦,我不太明白它在做什么。这是 hexdump 的摘录,我尽力对其进行了注释:
正确解析:
000001a0 0a 32 30 32 31 2d 31 31 2d 32 34 16 02 00 18 07 |.2021-11-24.....|
........................blah blah blah............| | |
Object End-| | |
0x18 & 0xF = 0x8 = Binary-| |
The binary sequence is 0x7 characters long-|
000001b0 53 65 61 74 74 6c 65 18 02 55 53 18 02 55 53 18 |Seattle..US..US.|
S E A T T L E |___| U S |___| U S
Another string, 2 bytes long |------------|
到目前为止一切顺利。
但后来我想到了这一点:
我要提取的字符串是 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4592.0 Safari/537.36 Edg/94.0.975.1"
并且长 134 个字节。
000001c0 09 54 61 68 6f 65 2c 20 43 41 12 12 00 00 08 c8 |.Tahoe, CA......|
Object ends here-| | |
0x8 & 0xF = 0x8 = Binary -| |
0xc8 bytes long (200)-|
000001d0 01 86 01 4d 6f 7a 69 6c 6c 61 2f 35 2e 30 20 28 |...Mozilla/5.0 (|
| | | M o z i l l a
???? |--|-134, encoded as var-int
000001e0 4d 61 63 69 6e 74 6f 73 68 3b 20 49 6e 74 65 6c |Macintosh; Intel|
如您所见,我有一个字节序列 0x08 0xC8 0x01 0x86 0x01
,其中包含我正在寻找的字符串的长度,后面是我正在寻找的字符串,但有 3 个额外的字节目的不明确。
0x01
尤其令人困惑,因为它既不是类型标识符,也似乎没有具体值。
我错过了什么?
Thrift 支持可插入序列化方案。在树中,你有二进制、紧凑和 json。出了树什么都行。看样子你是在尝试解码紧凑协议,所以我会相应地回答。
Thrift RPC 调用中发送的所有内容和返回的所有内容都打包在一个结构中。结构中的每个字段都有一个 1 字节类型和一个 2 字节字段 ID 前缀。在紧凑协议中,字段 id 在可能的情况下被增量编码到类型中,并且所有 int 都被压缩到仅存储它们所需的位(和一些标志)。因为 int 现在可以占用不同数量的字节,所以我们需要知道它们何时结束。 Compact 协议将 int 位编码为一个字节的 7 位,如果下一个字节继续 int,则将高位设置为 1。如果高位为 0,则 int 完成。因此 int 5 (101) 将在一个字节中编码为 0000101。Compact 知道这是 int 的结尾,因为高位是 0.
在您的例子中,int 134(二进制 10000110)将需要 2 个字节进行编码,因为它超过 7 位。前 7 位存储在字节 1 中,0x80 位设置为标志“int continues”。第二个也是最后一个字节对最后一位 (00000001) 进行编码。你以为的 134 只是前七位的编码。杂散的 1 是 134 的最后一位。
我建议您使用 in tree 源来执行任何需要的协议 encoding/decoding。它已经编写和测试:https://github.com/apache/thrift/blob/master/lib/nodejs/lib/thrift/compact_protocol.js
字节序列如下
0x08
:String类型,后面2个字节定义elementId
0xC8 0x01
:ElementId,16位编码
0x86 0x01
:字符串长度,编码为 var int
事实证明,如果类型标识符不包含定义 elementId 的位,则 elementId 将存储在接下来的 2 个字节中。
我正在编写一个不依赖于 thrift 定义的纯 JS thrift 解码器。我一直在关注这个方便的指南,它是我过去几天的圣经:https://erikvanoosten.github.io/thrift-missing-specification/
我的解析器几乎可以正常工作了,但是有一个字符串类型给程序带来了麻烦,我不太明白它在做什么。这是 hexdump 的摘录,我尽力对其进行了注释:
正确解析:
000001a0 0a 32 30 32 31 2d 31 31 2d 32 34 16 02 00 18 07 |.2021-11-24.....|
........................blah blah blah............| | |
Object End-| | |
0x18 & 0xF = 0x8 = Binary-| |
The binary sequence is 0x7 characters long-|
000001b0 53 65 61 74 74 6c 65 18 02 55 53 18 02 55 53 18 |Seattle..US..US.|
S E A T T L E |___| U S |___| U S
Another string, 2 bytes long |------------|
到目前为止一切顺利。
但后来我想到了这一点:
我要提取的字符串是 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4592.0 Safari/537.36 Edg/94.0.975.1"
并且长 134 个字节。
000001c0 09 54 61 68 6f 65 2c 20 43 41 12 12 00 00 08 c8 |.Tahoe, CA......|
Object ends here-| | |
0x8 & 0xF = 0x8 = Binary -| |
0xc8 bytes long (200)-|
000001d0 01 86 01 4d 6f 7a 69 6c 6c 61 2f 35 2e 30 20 28 |...Mozilla/5.0 (|
| | | M o z i l l a
???? |--|-134, encoded as var-int
000001e0 4d 61 63 69 6e 74 6f 73 68 3b 20 49 6e 74 65 6c |Macintosh; Intel|
如您所见,我有一个字节序列 0x08 0xC8 0x01 0x86 0x01
,其中包含我正在寻找的字符串的长度,后面是我正在寻找的字符串,但有 3 个额外的字节目的不明确。
0x01
尤其令人困惑,因为它既不是类型标识符,也似乎没有具体值。
我错过了什么?
Thrift 支持可插入序列化方案。在树中,你有二进制、紧凑和 json。出了树什么都行。看样子你是在尝试解码紧凑协议,所以我会相应地回答。
Thrift RPC 调用中发送的所有内容和返回的所有内容都打包在一个结构中。结构中的每个字段都有一个 1 字节类型和一个 2 字节字段 ID 前缀。在紧凑协议中,字段 id 在可能的情况下被增量编码到类型中,并且所有 int 都被压缩到仅存储它们所需的位(和一些标志)。因为 int 现在可以占用不同数量的字节,所以我们需要知道它们何时结束。 Compact 协议将 int 位编码为一个字节的 7 位,如果下一个字节继续 int,则将高位设置为 1。如果高位为 0,则 int 完成。因此 int 5 (101) 将在一个字节中编码为 0000101。Compact 知道这是 int 的结尾,因为高位是 0.
在您的例子中,int 134(二进制 10000110)将需要 2 个字节进行编码,因为它超过 7 位。前 7 位存储在字节 1 中,0x80 位设置为标志“int continues”。第二个也是最后一个字节对最后一位 (00000001) 进行编码。你以为的 134 只是前七位的编码。杂散的 1 是 134 的最后一位。
我建议您使用 in tree 源来执行任何需要的协议 encoding/decoding。它已经编写和测试:https://github.com/apache/thrift/blob/master/lib/nodejs/lib/thrift/compact_protocol.js
字节序列如下
0x08
:String类型,后面2个字节定义elementId0xC8 0x01
:ElementId,16位编码0x86 0x01
:字符串长度,编码为 var int
事实证明,如果类型标识符不包含定义 elementId 的位,则 elementId 将存储在接下来的 2 个字节中。