FAST协议详解4 存在图PMap
一、概述
存在图是比较基础但又非常重要的一个设定,如果存在图没搞对后面的解析肯定是有问题的。但要说清楚存在图又必须先搞明白各种数据类型、操作符、可空属性,所以存在图虽然在FAST数据流的最前面但又不得不放到最后来说。
二、存在图的基本设定
存在图主要与操作符类型强相关,但又与可空属性和数据类型有一点关系,这里我们以操作符作为主索引,依次进行实例演示。
操作符 |
可空属性 |
PMap |
说明 |
DEFAULT默认 |
False/True |
占1位 |
字段使用DEFAULT操作符后,在PMap中将占用1位用以表示是否有传输该字段值。若PMap中该位值为0,表明未传递值,则该字段解析结果为“默认值”。若PMap中该位值为1,表明有传递值,则该字段解析结果以传递值为准。 |
COPY复制 |
False/True |
占1位 |
字符使用COPY操作符后,在PMap中将占用1位用以表示是否有传输该字段值。若PMap中该位值为0,表明未传递值,则该字段解析结果为“上一次传输的值--即复制”。若PMap中该位值为1,表明有传递值,则该字段解析结果以传递值为准。 |
INCREMENT递增 |
False/True |
占1位 |
字符使用INCREMENT操作符后,在PMap中将占用1位用以表示是否有传输该字段值。若PMap中该位值为0,表明未传递值,则该字段解析结果为“上一次传输的值+1”。若PMap中该位值为1,表明有传递值,则该字段解析结果以传递值为准。 |
TAIL接尾 |
False/True |
占1位 |
字符使用TAIL操作符后,在PMap中将占用1位用以表示是否有传输该字段值。若PMap中该位值为0,表明未传递值,则该字段解析结果为“上一次传输的值”。若PMap中该位值为1,表明有传递值,则该字段解析结果为上一次传输值+接尾部分。 |
CONSTANT常量 |
False |
不占位 |
字段使用CONSTANT操作符且可空属性为False时,在PMap中不占位。编码时无论该字段是否有设置值,流中均不传输任何值,解析方只根据预设的常量值解析。 |
CONSTANT常量 |
True |
占1位 |
字段使用CONSTANT操作符且可空属性为True时,在PMap中占1位。编码时若该字段有设置值,则PMap中该位值为1,表明字段不为空,应解析为预设值。编码时若该字段未设置值,则PMap中该位值为0,表明字段为空,应解析为null。 |
NONE无 |
False/True |
不占位 |
字段使用NONE操作符时,在PMap中不占位。即FAST流中一定会传输该字段值。 |
三、实例
1、DEFAULT默认操作符
操作符 |
可空属性 |
PMap |
说明 |
DEFAULT默认 |
False/True |
占1位 |
字段使用DEFAULT操作符后,在PMap中将占用1位用以表示是否有传输该字段值。若PMap中该位值为0,表明未传递值,则该字段解析结果为“默认值”。若PMap中该位值为1,表明有传递值,则该字段解析结果以传递值为准。 |
上述代码运行结果如下:
msg111= -> {123, 1}
msg111= -> {123, 2}
msg111= -> {123, 3}
outByteStr=11100000,11111011,10000001,10000000,10100000,10000011,
二进制数据解析如下:
提前说明:需要注意模版ID字段在PMap中须占1位,根据“二、存在图的基本设定”,这里数据字段在PMap中须占1位。
二进制数 |
解码结果 |
说明 |
11100000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明有传输该字段 第三位是数据字段,这里表明有传输该字段 |
11111011 |
123 |
根据PMap得知有传输模版ID字段,故模版ID=123 |
10000001 |
1 |
根据PMap得知有传输数据字段,故数据字段=1 |
10000000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 第三位是数据字段,这里表明未传输该字段,根据字段属性,数据字段的值应该=2(默认值) |
10100000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 第三位是数据字段,这里表明传输了数据字段 |
10000011 |
3 |
根据PMap得知有传输数据字段,故数据字段=3 |
问题:将可空属性修改为true如何
上述代码运行结果如下:
msg111= -> {123, 1}
msg111= -> {123, 2}
msg111= -> {123, null}
outByteStr=11100000,11111011,10000010,10000000,10100000,10000000,
二进制数据解析如下:
二进制数 |
解码结果 |
说明 |
11100000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明有传输该字段 第三位是数据字段,这里表明有传输该字段 |
11111011 |
123 |
根据PMap得知有传输模版ID字段,故模版ID=123 |
10000010 |
1 注:由于字段是可空的,所以需要自减1 |
根据PMap得知有传输数据字段,故数据字段=1 |
10000000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 第三位是数据字段,这里表明未传输该字段,根据字段属性,数据字段的值应该=2(默认值) |
10100000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 第三位是数据字段,这里表明传输了数据字段 |
10000000 |
Null |
根据PMap得知有传输数据字段,故数据字段=null |
需要注意的是,由于可空属性,不设置该字段值时,也实际传递了10000000,同时PMap中第三位被置1表明传递了值。
问题:其他数据类型结果一致吗?
验证一致
2、COPY复制操作符
操作符 |
可空属性 |
PMap |
说明 |
COPY复制 |
False/True |
占1位 |
字符使用COPY操作符后,在PMap中将占用1位用以表示是否有传输该字段值。若PMap中该位值为0,表明未传递值,则该字段解析结果为“上一次传输的值--即复制”。若PMap中该位值为1,表明有传递值,则该字段解析结果以传递值为准。 |
上述代码运行结果如下:
msg111= -> {123, 1}
msg111= -> {123, 2}
msg111= -> {123, 2}
outByteStr=11100000,11111011,10110001,10100000,10110010,10000000,
二进制数据解析如下:
二进制数 |
解码结果 |
说明 |
11100000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明有传输该字段 第三位是数据字段,这里表明有传输该字段 |
11111011 |
123 |
根据PMap得知有传输模版ID字段,故模版ID=123 |
10110001 |
49 |
根据PMap得知有传输数据字段,故数据字段=“1” |
10100000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 第三位是数据字段,这里表明有传输该字段 |
10110010 |
50 |
根据PMap得知有传输数据字段,故数据字段=“2” |
10000000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 第三位是数据字段,这里表明未传输该字段,根据操作符COPY得知应复制上一次传输的结果“2”。 |
3、INCREMENT复制操作符
操作符 |
可空属性 |
PMap |
说明 |
INCREMENT递增 |
False/True |
占1位 |
字符使用INCREMENT操作符后,在PMap中将占用1位用以表示是否有传输该字段值。若PMap中该位值为0,表明未传递值,则该字段解析结果为“上一次传输的值+1”。若PMap中该位值为1,表明有传递值,则该字段解析结果以传递值为准。 |
上述代码运行结果如下:
msg111= -> {123, 1}
msg111= -> {123, 3}
msg111= -> {123, 4}
outByteStr=11100000,11111011,10000001,10100000,10000011,10000000,
二进制数据解析如下:
二进制数 |
解码结果 |
说明 |
11100000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明有传输该字段 第三位是数据字段,这里表明有传输该字段 |
11111011 |
123 |
根据PMap得知有传输模版ID字段,故模版ID=123 |
10000001 |
1 |
根据PMap得知有传输数据字段,故数据字段=1 |
10100000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 第三位是数据字段,这里表明有传输该字段 |
10000011 |
3 |
根据PMap得知有传输数据字段,故数据字段=3 |
10000000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 第三位是数据字段,这里表明未传输该字段,根据操作符INCREMENT得知应将上一次传输的值+1,既=4。 |
4、TAIL接尾操作符
操作符 |
可空属性 |
PMap |
说明 |
TAIL接尾 |
False/True |
占1位 |
字符使用TAIL操作符后,在PMap中将占用1位用以表示是否有传输该字段值。若PMap中该位值为0,表明未传递值,则该字段解析结果为“上一次传输的值”。若PMap中该位值为1,表明有传递值,则该字段解析结果为上一次传输值+接尾部分。 |
上述代码运行结果如下:
msg111= -> {123, 111}
msg111= -> {123, 111}
msg111= -> {123, 112}
outByteStr=11100000,11111011,00110001,00110001,10110001,10000000,10100000,10110010,
二进制数据解析如下:
二进制数 |
解码结果 |
说明 |
11100000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明有传输该字段 第三位是数据字段,这里表明有传输该字段 |
11111011 |
123 |
根据PMap得知有传输模版ID字段,故模版ID=123 |
00110001,00110001,10110001 |
“111” |
根据PMap得知有传输数据字段,故数据字段=“111” |
10000000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 第三位是数据字段,这里表明未传输该字段,根据操作符TAIL得知应解析为上一次传输的值“111” |
10100000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 第三位是数据字段,这里表明有传输该字段值 |
10110010 |
“2” |
根据操作符TAIL的特性,应将“111”的最后一位替换为“2”,既最终解析结果为“112” |
5、DEFAULT默认操作符1
操作符 |
可空属性 |
PMap |
说明 |
CONSTANT常量 |
False |
不占位 |
字段使用CONSTANT操作符且可空属性为False时,在PMap中不占位。编码时无论该字段是否有设置值,流中均不传输任何值,解析方只根据预设的常量值解析。 |
上述代码运行结果如下:
msg111= -> {123, 2}
msg111= -> {123, 2}
msg111= -> {123, 2}
outByteStr=11000000,11111011,10000000,10000000,
二进制数据解析如下:
二进制数 |
解码结果 |
说明 |
11000000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明有传输该字段 对于CONSTANT操作符的字段,不占用PMap位,直接解析出预设值2 |
11111011 |
123 |
根据PMap得知有传输模版ID字段,故模版ID=123 |
10000000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 对于CONSTANT操作符的字段,不占用PMap位,直接解析出预设值2 |
10000000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 对于CONSTANT操作符的字段,不占用PMap位,直接解析出预设值2 |
问题:CONSTANT是否可以在编码时不设置值
上述代码运行结果如下:
msg111= -> {123, 2}
msg111= -> {123, 2}
msg111= -> {123, 2}
outByteStr=11000000,11111011,10000000,10000000,
可见编码时无论是否设置值,解码都会解码成预设的值,且FAST流中不会传输该字段值。
问题:在编码时是否可以设置与预设值不一样的?
答:实践证明不行,会报错
6、DEFAULT默认操作符2
操作符 |
可空属性 |
PMap |
说明 |
CONSTANT常量 |
True |
占1位 |
字段使用CONSTANT操作符且可空属性为True时,在PMap中占1位。编码时若该字段有设置值,则PMap中该位值为1,表明字段不为空,应解析为预设值。编码时若该字段未设置值,则PMap中该位值为0,表明字段为空,应解析为null。 |
上述代码运行结果如下:
msg111= -> {123, 2}
msg111= -> {123, 2}
msg111= -> {123, 2}
outByteStr=11100000,11111011,10100000,10100000,
上述代码运行结果如下:
msg111= -> {123, null}
msg111= -> {123, null}
msg111= -> {123, null}
outByteStr=11000000,11111011,10000000,10000000,
7、NONE无操作符
操作符 |
可空属性 |
PMap |
说明 |
NONE无 |
False/True |
不占位 |
字段使用NONE操作符时,在PMap中不占位。即FAST流中一定会传输该字段值。 |
上述代码运行结果如下:
msg111= -> {123, 1}
msg111= -> {123, 2}
msg111= -> {123, 3}
outByteStr=11000000,11111011,10000001,10000000,10000010,10000000,10000011,
二进制数据解析如下:
二进制数 |
解码结果 |
说明 |
11000000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明有传输该字段 |
11111011 |
123 |
根据PMap得知有传输模版ID字段,故模版ID=123 |
10000001 |
1 |
对于NONE操作符字段,不看PMap,一定会传输值,故这里数据字段解析为1 |
10000000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 |
10000010 |
2 |
对于NONE操作符字段,不看PMap,一定会传输值,故这里数据字段解析为2 |
10000000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 |
10000011 |
3 |
对于NONE操作符字段,不看PMap,一定会传输值,故这里数据字段解析为3 |
问题:可空情况的处理
上述代码运行结果如下:
msg111= -> {123, 1}
msg111= -> {123, null}
msg111= -> {123, 3}
outByteStr=11000000,11111011,10000010,10000000,10000000,10000000,10000100,
二进制数据解析如下:
二进制数 |
解码结果 |
说明 |
11000000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明有传输该字段 |
11111011 |
123 |
根据PMap得知有传输模版ID字段,故模版ID=123 |
10000010 |
1 |
对于NONE操作符字段,不看PMap,一定会传输值,故这里数据字段解析为2-1=1(可空字段要自行-1) |
10000000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 |
10000000 |
Null |
对于NONE操作符字段,不看PMap,一定会传输值,故这里数据字段解析为null(可空字段0就是null) |
10000000 |
PMap |
PMap第一位是停止位 第二位是模版ID,这里表明未传输该字段,则模版ID值沿用上一次的结果=123 |
10000100 |
3 |
对于NONE操作符字段,不看PMap,一定会传输值,故这里数据字段解析为4-1=3(可空字段要自行-1) |
四、回顾
通过实例分析可见,PMap其实与操作符强相关,且大部分操作符都会使字段在PMap中占1位,占位目的是为了通过0和1来标识字段是否传输值,比如copy操作符,如对应PMap位为1则表明不传输该字段值,则解码时自动复制上一次解码结果。