MQTT-java 深入理解PAYLOAD解析

前言

关于MQTT基础课程系列(HIVEMQ)的【译文】工作已结束,期间有一些术语实在难以翻译为可理解的中文技术用语。为了进一步理解MQTT特性,本篇文章将通过自定义解析PAYLOAD的方式,来解惑分析MQTT规范中特定术语。

目标

解析PAYLOAD内容

准备

  1. 参见 "MQTT 实践" ,"MQTT-Java 连接协议" 完成测试工程配置
  2. 代码仓库:github.com/harveyblack...
  3. 协议规范:docs.oasis-open.org/mqtt/mqtt/v...

了解PAYLOAD

描述

有些MQTT控制包含一个payload, 并把它作为控制包的最后一部分。在PUBLISH控制包中,payload就是一个应用消息

数据包整体结构

先前文章"MQTT-java MQTT控制包格式(MQTT Control Packet format)"

包含PAYLOAD的控制包

控制包名称 选项 描述
CONNECT 必须 连接代理服务器(broker)
SUBSCRIBE 必须 订阅主题
SUBACK 必须 订阅ACK
UNSUBSCRIBE 必须 解除主题的订阅
UNSUBACK 必须 解除主题的订阅ACK
PUBLISH 可选 发布主题

解码PAYLOAD

CONNECT 控制包

1. MQTT规范

'3.1.3 CONNECT Payload'

2. 数据结构

  1. Client Identifier : Will Properties : Will Topic : Will Payload : User Name : Password
  2. 数据类型

想了解MQTT的数据类型,可参见"MQTT-java 数据描述(Data representation)"

  • ClientID : UTF-8 Encoded, 即:长度(2个字节)+ 编码内容
  • Will Properties
    • Property Length : Variable Byte
    • Will Delay Interval: Four Byte Integer
    • Payload Format Indicator: Byte
    • Message Expiry Interval: Four Byte Integer
    • Content Type : UTF-8 Encoded
    • Response Topic : UTF-8 Encoded
    • Correlation Data : Binary
    • User Property : UTF-8 String Pair
  • Will Topic : UTF-8 Encoded
  • Will Payload : Binary
  • User Name : UTF-8 Encoded
  • Password : Binary

3. 解码流程

根据CONNECT payload的结构来讲,共分5大部分,除ClientID没有前置条件,剩余部分都需要根据控制包头中的CONNECT Flags标志来作为前置条件来进行解码。

4. 代码片段

实验代码入口文件ExampleParsePayLoad.java

详细解析过程参见代码库中的HarveyDebug.java文件,方法名为:parsePayload()

ini 复制代码
/**
* header : 固定头和可变头
**/
public static void parsePayload(byte [] header, byte [] payload){

...

//3.1.3.1 Client Identifier (ClientID)
int payloadIndex = 0;
int clientIdentifierLength = (payload[payloadIndex] << 8)&0xff00 | payload[payloadIndex+1];

byte [] clientIdentifierB = new byte[clientIdentifierLength];
for(int k = 0; k < clientIdentifierLength; k++){
    clientIdentifierB[k] = payload[payloadIndex + k];
}

payloadIndex = payloadIndex + clientIdentifierLength;

String clientIdentifier = new String(clientIdentifierB, StandardCharsets.UTF_8);
d("Client Identifier: " + clientIdentifier);
...

}

SUBSCRIBE 控制包

1. MQTT规范

'3.8.3 SUBSCRIBE Payload'

2. 数据结构

  1. Topic Filter : Subscription Options
  2. 数据类型
    • Topic Filter : UTF-8 Encoded
    • Subscription Options : Byte

3. 解码流程

4. 代码片段

实验代码入口文件ExampleParsePayLoad.java

详细解析过程参见代码库中的HarveyDebug.java文件,方法名为:parsePayload()

ini 复制代码
/**
* header : 固定头和可变头
**/
public static void parsePayload(byte [] header, byte [] payload){

...

int payloadIndex = 0;

while (payloadIndex < payload.length) {

    {
        int willTopicLength = (payload[payloadIndex++] << 8) & 0xff00 | payload[payloadIndex++];
        byte[] willTopicB = new byte[willTopicLength];
        for (int k = 0; k < willTopicLength; k++) {
            willTopicB[k] = payload[payloadIndex + k];
        }
        payloadIndex = payloadIndex + willTopicLength;

        String contentType = new String(willTopicB, StandardCharsets.UTF_8);
        d("Topic Filters: " + contentType);
    }

    //Reserved Retain Handling RAP NL QoS
    String Reserved = ((payload[payloadIndex] & 0xc0) >> 6) + "";
    String RetainHandling = ((payload[payloadIndex] & 0x30) >> 4) + "";
    String RAP = ((payload[payloadIndex] & 0x8) >> 3) + "";
    String NL = ((payload[payloadIndex] & 0x4) >> 2) + "";
    String QoS = (payload[payloadIndex] & 0x3) + "";

    d("Reserved:" + Reserved + " , " + "RetainHandling:" + RetainHandling + " , " + "RAP:" + RAP + " , " + "NL:" + NL + " , " + "QoS:" + QoS);

    payloadIndex++;

}
...

}

SUBACK,UNSUBSCRIBE,UNSUBACK,PUBLISH 控制包

依据本篇文章前两个类型的分析过程和实验代码,可自行尝试解码一下控制包

相关推荐
小书房4 小时前
Kotlin的by
android·开发语言·kotlin·委托·by
jinanwuhuaguo5 小时前
(第二十八篇)OpenClaw成本与感知的奇点——从“Token封建制”到“全民养虾”的本体论地基
android·人工智能·kotlin·拓扑学·openclaw
xxjj998a6 小时前
Laravel4.x核心特性全解析
android·mysql·laravel
JoshRen6 小时前
2026教程:在Android Termux中集成Gemini 3镜像站实现移动端文档自动处理与摘要生成(附国内免费方案)
android
诸神黄昏EX7 小时前
Android Google KEY
android
一起搞IT吧7 小时前
Android性能系列专题理论之十一:block IO问题分析思路
android·嵌入式硬件·智能手机·性能优化
小妖6668 小时前
怎么用 tauri 创建编译 android 应用程序
android·tauri
鸟儿不吃草9 小时前
安卓实现左右布局聊天界面
android·开发语言·python
胡楚昊10 小时前
借Polar IOTS一道困难挑战题简单入门蓝牙流量分析
物联网·蓝牙
xxjj998a10 小时前
Laravel 1.x:PHP框架的原始魅力
android·php·laravel