1 剩余长度占用(1~4)个字节

剩余长度就是指后面跟了多少字节。
剩余长度一字节只用bit0~bit6这7位表示数据,用bit7表示进位标志,为1则说明有进位,为0则无进位。
1字节可表示的数据:0~127个字节=128个
$$
2^7-1=127
$$
4字节可表示的数据:0~268435455个字节=256*1024*1024=256M
$$
2^{28}-1=268435455
$$

2 剩余长度计算方法

bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
进位标志 数据 数据 数据 数据 数据 数据 数据

假设剩余长度为500,转换为十六进制显示就是0X1F4,转换为二进制显示就是0001 1111 0100。
先看前7位 (111 0100),因为前7位才是有效数据!
给bit7的进位标志置1:(表示产生进位了)

进位标志 bit6 bit5 bit4 bit3 bit2 bit1 bit0
1(有进位) 1 1 1 0 1 0 0

所以剩余长度第一个字节就是0XF4(1111 0100)。(500%128)|(0X80) = 116 | 0X80 = 0XF4
再看剩下的:

bit14 bit13 bit12 bit11 bit10 bit9 bit8 bit7
0 0 0 0 0 0 1 1

所以剩余长度第一个字节就是0X03。(500/128=3) = 0X03
用数组remainBytes来存就是:

1
2
3
4
5
6
7
8
int ramainBytes[2] = {0XF4, 0X01};
// 利用上面两个数据怎么算出剩余长度500?
// 0XF4 = 1111 0100
// 1.先把有进位的标志给去掉
// 1111 0100 --> 0111 0100 = 0X74 = 116
// 2.计算剩余长度
// 0X03 = 3
// remainLength = 3 * 128 + 116 = 384 + 116 = 500

3 剩余长度计算函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**************************************************
* 功能: mqtt 协议层获取剩余长度占用字节数
* 参数: len:剩余内容长度
* buf:剩余内容指针
* 返回: 剩余长度占用字节数
* 备注:无
* ************************************************/
static int32 MQTT_GetRemainBytes(uint32 len, uint8* buf)
{
uint32 bytes = 0;
// 假设len = 500
for (bytes = 1; bytes <= 4; bytes++)
{
// 1. *buf = len % 128 = 116
// 2. len = len / 128 = 500 / 128 = 3
// 4. *buf = len % 128 = 3 % 128 = 3 = 0X03
// 5. buf[0] = 0XF4, buf[1] = 0X03
*buf = len % 128;
len /= 128;

// 剩余长度超过 1 字节, bit 置 1
// 3.len > 3, *buf = *buf | 0X80 = 116 | 0X80 = 0XF4
if (len > 0)
{
*buf |= 0X80;
buf++;
}
else
{
return bytes;
}
}
return -1;
}