mqtt协议剩余长度字段编解码实现方案(java)
硅谷探秘者
2021-12-31发表
mqtt协议
0
0
1741
mqtt协议报文解析,参考:http://www.jiajiajia.club/blog/artical/kdv1qvpfgbh4/514
根据mqtt协议的定义,剩余长度字段是可变的,最少用一个字节最多四个字节来表示,而且每个字节的最高位不表示有效数据,用来表示有没有下一个字节。所以每个字节能表示的数据的最大值是128,所以剩余长度字段可表示的最大值是128 * 128 * 128 * 128
,则理论上能表示数据包大小的最大值是256M。
对剩余长度字段的编解码,可理解为128进制的运算。如果低位字节满128,则向高位字节进1。那么进位系数就是128。
下面是用一段代码描述对剩余长度字段的计算方法(java实现)。
public static void main(String[] args) throws Exception{
int length = 300;
final byte[] encode = encode(length);
System.out.println("编码:"+length);
for (byte b : encode) {
System.out.println(getBinaryStrFromByte(b));
}
System.out.println();
System.out.println("解码:"+decode(encode));
}
/**
* mqtt固定报文头剩余长度的编码方案
* @param x 字节大小
* @return 编码结果
*/
public static byte[] encode(int x){
byte encodeBytes[] = new byte[x < 2<<6 ? 1 : x < 2<<13 ? 2 : x < 2<<20 ? 3 : 4];
int encodeByte;
int i=0;
do{
// 128进制,满128进1
encodeByte = x % 128;
x = x / 128;
if( x > 0 )
// encodeByte | 128 保证最高位必须是1
encodeByte = encodeByte | 128;
encodeBytes[i]=(byte)encodeByte;
i+=1;
}while (x>0);
return encodeBytes;
}
/**
* mqtt固定报文头剩余长度的编码方案
* @param bytes 编码后的字节数据
* @return 解码后的字节剩余长度
*/
public static int decode(byte[] bytes){
// multiplier 进位系数,第一个字节的进位系数是1,第二个字节的进位系数是128,
// 第三个字节的进位系数是 128 * 128,第四个字节的进位系数是 128 * 128 * 128
int multiplier = 1;
int value = 0;
int i=0;
byte encodedByte;
do {
encodedByte = bytes[i];
// encodedByte & 127 去掉最高位的1,因为最高位不表示数据
value += (encodedByte & 127) * multiplier;
multiplier *= 128;
if (multiplier > 128 * 128 * 128)
return -1;
i+=1;
// (encodedByte & 128) != 0 代表encodedByte该字节的最高位是1,
// 所以根据mqtt对剩余字段长度的定义应该还有下一个字节。
}while ((encodedByte & 128) != 0);
return value;
}
/**
* 字节转二进制字符串
* @param encodeByte byte
* @return 二进制字符串
*/
public static String getBinaryStrFromByte(byte encodeByte){
StringBuilder result = new StringBuilder();
byte a = encodeByte; ;
for (int i = 0; i < 8; i++){
int i1 = a % 2;
result.append(i1>0?i1:-i1);
a=(byte)(a>>1);
}
return result.reverse().toString();
}