一、概述

FAST协议里不同的数据类型在编码时有非常大的区别,比如整数只需要将二进制数据转为十进制即可,而浮点数则需要先传小数点位数,再传一个整数,最后将二者结合起来才是最终结果。本篇使用openfast自设了一些数据并编码成FAST数据,再对这些FAST数据进行人工解码,以图看懂FAST协议是如何传递不同类型的数据。

 

二、数据类型

看接口文档,存在以下类型的数据:

数据类型

说明

备注

ascii

ASCII字符串类型

 

byteVector

字节向量类型

 

decimal

浮点数类型

 

int16

有符号整数

都是有符号整数,区别仅在于取值范围

int32

有符号整数

int64

有符号整数

int8

有符号整数

string

字符串

 

uInt16

无符号整数

都是无符号整数,区别仅在于取值范围

uInt32

无符号整数

uInt64

无符号整数

uInt8

无符号整数

浓缩一下:

数据类型

说明

备注

ascii

ASCII字符串类型

 

string

字符串

 

byteVector

字节向量类型

 

decimal

浮点数类型

 

int

有符号整数

 

uInt

无符号整数

 

 

三、不同数据类型的编码与解码

1、ASCII字符串类型

 

FAST协议详解1 不同数据类型的编码与解码_二进制数

 

使用上述代码输出为:

msg111= -> {123, 234}
outByteStr=11100000,11111011,00110010,00110011,10110100,

二进制数据解析如下:

二进制数

解码过程

解码结果

11100000

 

PMap

11111011

01111011=123

123

00110010,00110011,10110100

00110010=50=’2’

00110011=51=’3’

00110100=52=’4’

234

 

2、String字符串类型

 

FAST协议详解1 不同数据类型的编码与解码_FAST_02

 

使用上述代码输出为:

msg111= -> {123, 234}
outByteStr=11100000,11111011,00110010,00110011,10110100,

二进制数据解析如下:

二进制数

解码过程

解码结果

11100000

 

PMap

11111011

01111011=123

123

00110010,00110011,10110100

00110010=50=’2’

00110011=51=’3’

00110100=52=’4’

234

 

ASCII与string编码、解码一致,看不出区别。

 

3、int有符号整数类型

 

FAST协议详解1 不同数据类型的编码与解码_二进制数_03

 

使用上述代码输出为:

msg111= -> {123, 234}
outByteStr=11100000,11111011,00000001,11101010,

二进制数据解析如下:

二进制数

解码过程

解码结果

11100000

 

PMap

11111011

01111011=123

123

00000001,11101010

00000001=1*128=128

01101010=106

128+106=234

234

 

将输入修改为负值

msg111= -> {123, -234}
outByteStr=11100000,11111011,01111110,10010110

二进制数据解析如下:

二进制数

解码过程

解码结果

11100000

 

PMap

11111011

01111011=123

123

01111110,10010110

01111110->1111110

10010110->0010110

实际:11111100010110

=-234

-234

 

问题:有符号整数如何传输负值?

可以看到,在传输234这个值时,我们解码的方式是将2个字节分开,前面的字节转十进制后乘以128,后面的字节直接转十进制,然后两个十进制数相加。

在传输-234时,是两个字节分别去掉第一个位(停止位),拼接起来直接转成了十进制。

我们知道,在计算机中,对于有符号整数的二进制存储,是默认了,第一个位是1的话认为是负数,第一个位是0的话则认为是正数。这里也是一样,去掉每个字节的第一个位(停止位)后,第一个位如果是1则认为是负数,适用负数转换规则。第一个位如果是0则认为是正数,适用正数转换规则。

对于一些数值,刚好第一位是1该如何处理,比如126=1111110?

msg111= -> {123, 126}
outByteStr=11100000,11111011,00000000,11111110,

实例如上,只需要在前面补0即可。

 

4、uInt无符号类型

 

FAST协议详解1 不同数据类型的编码与解码_二进制数_04

 

使用上述代码输出为:

msg111= -> {123, 126}
outByteStr=11100000,11111011,11111110,

二进制数据解析如下:

二进制数

解码过程

解码结果

11100000

 

PMap

11111011

01111011=123

123

11111110

01111110=126

126

 

可见,对于无符号数,直接按正数规则解码即可。

 

5、decimal浮点数类型

 

FAST协议详解1 不同数据类型的编码与解码_浮点数_05

 

使用上述代码输出为:

msg111= -> {123, 234.456}
outByteStr=11100000,11111011,11111101,00001110,00100111,11011000,

二进制数据解析如下:

二进制数

解码过程

解码结果

11100000

 

PMap

11111011

01111011=123

123

11111101

11111101=-3

-3

00001110,00100111,11011000

00001110=14

00100111=39

01011000=88

14*128*128+39*128+88=234456

234456

很容易看明白,对浮点数进行编码时分成了2个部分,第一部分是“小数点”位数,第二部分是整数。解码后将两部分合并才能得到最终结果。

 

问题:如何传递负浮点数?

将234.456修改为-234.456后,输出为:

msg111= -> {123, -234.456}

outByteStr=11100000,11111011,11111101,01110001,01011000,10101000,

二进制数据解析如下:

二进制数

解码过程

解码结果

11100000

 

PMap

11111011

01111011=123

123

11111101

11111101=-3

-3

01110001,01011000,10101000

111000110110000101000=-234456

-234456

与有符号整数差不多,是否传递负数,只需要将除去“停止位”后,判断第一个位是否是“1”即可。所以只需要将浮点数的传递看成是“小数点”+“整数”两个部分即可。

 

6、byteVector字节向量类型

前面我们讨论了整数、浮点数、字符串,所有的编码其实都遵循了一个原则,即一个字节能够传递的最大值只能小于128,要传递更大的值则需要“进位”。但我们需要传递的字节一定要大于128该如何是好,比如中文。我们使用前面的字符串、ASCII、整数,也不是不能编码,但解码起来就有点麻烦。很明显这时候就可以用到字节向量。

 

FAST协议详解1 不同数据类型的编码与解码_字符串_06

 

使用上述代码输出为:

msg111= -> {123, ????????}
outByteStr=11100000,11111011,10001000,11001110,11111011,11001110,11111011,10111001,11111110,10111001,11111110,

二进制数据解析如下:

二进制数

解码过程

解码结果

11100000

 

PMap

11111011

01111011=123

123

10001000

00001000=8

8个字节

11001110,11111011,

11001110,11111011,

10111001,11111110,

10111001,11111110

11001110,11111011=CE FB

11001110,11111011=CE FB

10111001,11111110=B9 FE

10111001,11111110=B9 FE

CEFB CEFB B9FE B9FE=嘻嘻哈哈

嘻嘻哈哈

有点类似浮点数的编码,这里先传递字节向量的长度“8”,接着传递字节向量。由于字节向量的长度已指定,故传输数据时不再遵循停止位的概念。

另注意这里使用的是GBK编码,故直接输出是乱码。

 

四、回顾

数据类型

说明

备注

ascii

ASCII字符串类型

遵循一般停止位规则,最后一个字节的第一位为1则是该字段最后一个字节,而后根据ASCII码表直接转字符串即可。

string

字符串

同上

int

有符号整数

遵循一般停止位规则,注意第一位(除开停止位之外的)为“0”则是正整数,则按128进位的规则进行数值转换即可。第一位(除开停止位之外的)为“1”则是负整数,则将全部字节去掉停止位后,直接转为整数即可。负数转换时需要注意前面要补1。

uInt

无符号整数

遵循一般停止位规则,由于知道一定是正整数,则直接按128进位的规则进行数值转换即可。

decimal

浮点数类型

分两部分进行传递,两个部分均遵循一般停止位规则。第一部分是浮点数的“小数点位数”,第二部分则是整数。注意是有符号整数,遵循int的解码方式即可。

byteVector

字节向量类型

分两部分进行传递,第一部分是字节向量的长度,遵循一般停止位规则。第二部分则是纯byte数据,不再遵循停止位规则,但由于前面有传递其长度,故也不会出错。

 

结语:这里只是最基本的编码解码规则,到这里也只是能稍微看懂一点还无法进行真正的FAST解码。后面的“操作符”及null什么的才是硬骨头。