涉及到通信的地方就会需要通信协议,因为只有确定了通信协议,通信双方才能理解对方所发来的数据有什么含义。BER(Basic Encoding Rule)是一种编码规格说明,描述如何将ASN.1类型的值编码成字符串(string of octets)的方法。BER的数据都是由三个域构成:标识域(Tag)+长度域(Length)+值域(Value),简称TLV格式。
1. TLV 简介
TLV 是一种可变的格式,其中:T 可以理解为 Tag 或 Type ,用于标识标签或者编码格式信息;
L 定义数值的长度;
V 表示实际的数值。
T 和 L 的长度固定,一般是2或4个字节,V 的长度由 Length 指定。
2. 字节序
要正确的解析对方发来的数据除了统一数据格式之外还要统一字节序。字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。字节序一般分为大端和小端。
2.1 大端和小端
大端模式(Big-Endian): 高位字节放在内存的低地址端,低位字节排放在内存的高地址端。
小端模式(Little-Endian): 低位字节放在内存的低地址端,高位字节放在内存的高地址端。
下面举个例子,要把0x1234 存放在 0x2000 地址处,那么大端模式和小端模式存放方式如下:
2.2 网络字节序
网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用Big-Endian排序方式。
为了进行转换 bsd socket提供了转换的函数 有下面四个htons 把unsigned short类型从主机序转换到网络序
htonl 把unsigned long类型从主机序转换到网络序
ntohs 把unsigned short类型从网络序转换到主机序
ntohl 把unsigned long类型从网络序转换到主机序
3. 编解码
假设 Tag(或 Type)和 Length 都是 4字节表示(unsigned long)。
3.1 编码步骤使用 htonl 将 Tag(或Type)转成网络字节序,指针偏移 4;
使用 htonl 将 Length 转成网络字节序,指针偏移 4;
若值 Value 为 int、char、short、long 类型,将其转为网络字节序,指针偏移;若值为字符串,写入后指针偏移 Length;
重复上述三步,继续编码后面的 TLV 单元。
3.2 解码步骤读取 Tag(或Type)并使用 ntohl 将其转成主机字节序,指针偏移4;
读取 Length ntohl** 将其转成主机字节序,指针偏移4;
根据得到的长度读取 Value,若为 int、char、short、long 类型,将其转为主机字节序,指针偏移;若值为字符串,读取后指针偏移 Length;
重复上述三步,继续读取后面的 TLV 单元。
参考链接: