pvAccess协议数据编码
1. 协议概述
pvAccess协议是一种用于分布式系统通信的协议,支持高效的数据序列化与反序列化。其数据编码设计强调灵活性、高效性和跨平台兼容性,支持多种数据类型(标量、数组、结构、联合等),并通过元数据(如内省数据、位集)实现动态类型管理和部分序列化优化。
2. 数据编码规则
2.1 大小(Size)编码
规则:
- 空值(Null):用单字节0xFF表示。
- 元素数 < 254:直接以1字节无符号整数编码。
- 元素数 < 2³¹-1:首字节0xFE,后接32位有符号整数。
- 元素数 ≥ 2³¹-1:暂不支持,但预留扩展方案(首字节0xFE,后接0x7FFFFFFF及64位整数)。
限制:最大支持元素数为2⁶³-1,但实际实现受限于协议版本。
2.2 字节序处理
-
连接导向协议(如TCP)需通过SET_ENDIANESS控制消息协商字节序,而非依赖消息头的字节序标志。
-
无连接协议(如UDP)由发送方决定字节序,接收方需自适应解析。
3. 基本类型编码
类型 | 编码方式 |
---|---|
布尔值 | 1字节(0为false,非零为true,发送方无需统一非零值)。 |
整数 | 二补码表示(8/16/32/64位),如byte(8位)、short(16位)。 |
无符号整数 | 直接二进制表示,如ubyte(8位)、ulong(64位)。 |
浮点数 | 遵循IEEE-754标准(float为32位单精度,double为64位双精度)。 |
4. 复合类型编码
4.1 数组
-
可变数组:大小+元素序列(如03 01 02 03)。
-
有界数组:大小≤预设上限(如byte<16>最多16元素)。
-
固定数组:无需大小字段,严格按定义长度解析(如byte[4]必须4元素)。
4.2 字符串
-
编码为UTF-8字节数组,前置大小字段(字节数,非字符数)。
-
有界字符串:大小不得超过预设界限,编码方式与普通字符串相同。
-
禁止终止符:内部实现若使用\0,序列化时需剔除。
4.3 结构体(Structure)
按字段定义顺序依次编码各成员。
结构数组:每个元素前加存在标志(0x00表示空,0x01后接结构数据)。
示例:
结构体数组[{0x1111, 0x2222}, null, {0x3333, 0x4444}]编码为:
03 01 11 11 22 22 00 01 33 33 44 44
4.4 联合(Union)与变体联合(Variant Union)
-
普通联合:编码为选择器值(size类型)后接所选成员数据。
-
变体联合:编码为内省描述(Field类型)后接实际数据,支持开放类型。
5. 元数据编码
5.1 位集(BitSet)
编码方式:按8位组序列化,低位优先(LSB到MSB),优化传输时剔除尾部零。
示例:
{8}:编码为02 00 01(3字节,表示第8位为1)。
{0,1,2,4}:编码为01 17(二进制00010111)。
5.2 部分结构序列化
通过位集标记序列化的字段,仅传输变更部分。
位分配规则:结构体内每个字段对应一个位,若父结构位被设置,则所有子字段必须序列化。
6. 状态(Status)编码
标准结构:
struct Status {
byte type; // 枚举:OK(0), WARNING(1), ERROR(2), FATAL(3)
string message; // 可选错误信息
string callTree; // 调用栈信息(可选)
};
优化:若状态为OK且无附加信息,可简化为StatusOK结构(单字节0xFF)。
示例:
StatusOK:FF
WARNING, "Low memory", "":01 0A 4C 6F 77 20 6D 65 6D 6F 72 79 00
7. 内省数据(Introspection Data)
7.1 编码类型
类型码 | 描述 |
---|---|
NULL_TYPE_CODE | 无内省数据(单字节0xFF)。 |
ONLY_ID_TYPE_CODE | 仅发送类型ID(0xFE后接ID)。 |
FULL_WITH_ID_TYPE_CODE | 发送ID及完整类型描述(0xFD后接ID及字段描述)。 |
FULL_TAGGED_ID_TYPE_CODE | 含ID、标签及类型描述(0xFC后接ID、标签及描述)。 |
7.2 动态类型管理
ID分配:发送方动态分配短整型ID,接收方缓存ID与类型描述的映射。
复用优化:首次发送使用完整描述,后续使用ID减少数据量。
示例:
时间戳结构体的内省数据编码(部分):
FD 00 01 80 0B 74 69 6D 65 53 74 61 6D 70 5F 74 ...
8. 示例分析
8.1 结构体编码示例
给定结构体:
structure {
byte[] value [1,2,3];
byte<16> boundedSizeArray [4,5,6,7,8];
byte[4] fixedSizeArray [9,10,11,12];
// …嵌套结构体及联合
}
编码结果:
03 01 02 03 05 04 05 06 07 08 09 0A 0B 0C ...
03:可变数组大小(3元素)
05:有界数组大小(5元素)
固定数组直接编码4元素。
8.2 内省数据示例
复杂结构体的内省数据通过FULL_WITH_ID_TYPE_CODE编码,包含类型ID、字段名称及嵌套结构描述。
9. 协议实现注意事项
字节序协商:TCP连接需通过控制消息协商字节序,而非依赖消息头标志。
大小限制:当前不支持≥2³¹-1元素的数组,需预留扩展接口。
内省数据缓存:接收方需维护类型ID映射表以支持复用。
性能优化:利用部分序列化(位集标记)减少数据传输量。
10. 总结
pvAccess协议通过灵活的数据编码机制和元数据管理,实现了高效、可扩展的通信能力。其设计特点包括:
类型自描述:内省数据支持动态类型解析。
传输优化:位集标记和部分序列化减少冗余数据传输。
跨平台兼容:明确的字节序协商和标准编码规则(如IEEE-754)。
未来改进方向可包括支持更大规模数据集、增强内省数据的版本兼容性,以及进一步优化变体联合的解析效率。