Mqtt-Java深入理解有效载荷解析
作者:访客发布时间:2023-10-26分类:程序开发学习浏览:136
导读:前言关于mqtt基础课程系列(HIVEMQ)的[译文]工作已结束,期间有一些术语实在难以翻译为可理解的中文技术用语.为了进一步理解mqtt特性,本篇文章将通过自定义解析有效载荷的方...
前言
关于mqtt基础课程系列(HIVEMQ)的[译文]工作已结束,期间有一些术语实在难以翻译为可理解的中文技术用语.为了进一步理解mqtt特性,本篇文章将通过自定义解析有效载荷的方式,来解惑分析mqtt规范中特定术语。
目标
解析有效负载内容
准备
- 参见“mqtt实践”,“mqtt-JAVA连接协议”完成测试工程配置
- 代码仓库:githeb.com/harveyBlack…
- 协议规范:docs.oASIS-Open.org/mqtt/mqtt/v…
了解有效负载
描述
有些MQTT控制包含一个有效载荷,并把它作为控制包的最后一部分。在发布控制包中,有效负载就是一个应用消息
数据包整体结构
先前文章“mqtt-Java mqtt控制包格式(mqtt控制包格式)”
包含有效负载的控制包
控制包名称 | 选项 | 描述 |
---|---|---|
连接 | 必须 | 连接代理服务器(经纪商) |
订阅 | 必须 | 订阅主题 |
子确认 | 必须 | 订阅确认 |
取消订阅 | 必须 | 解除主题的订阅 |
取消退货确认 | 必须 | 解除主题的订阅确认 |
发布 | 可选 | 发布主题 |
解码有效负载
连接控制包
1.mqtt规范
‘3.1.3连接有效负载’
2.数据结构
- 客户端标识符:Will属性:Will主题:Will负载:用户名:密码
- 数据类型
想了解mqtt的数据类型,可参见“mqtt-Java数据描述(数据表示)”
- 客户端ID:UTF-8编码,即:长度(2个字节)+编码内容
- 遗嘱属性
- 属性长度:可变字节
- 将延迟间隔:四字节整数
- 有效载荷格式指示符:字节
- 消息过期间隔:四字节整数
- 内容类型:UTF-8编码
- 响应主题:UTF-8编码
- 关联数据:二进制
- 用户属性:UTF-8字符串对
- Will主题:UTF-8编码
- 将负载:二进制
- 用户名:UTF-8编码
- 密码:二进制
3.解码流程
根据连接有效负载的结构来讲,共分5大部分,除客户端ID没有前置条件,剩余部分都需要根据控制包头中的连接标志标志来作为前置条件来进行解码。
4.代码片段
实验代码入口文件ExampleParsePayLoad.java
详细解析过程参见代码库中的HarveyDebug.java
文件,方法名为:parsePayload()
/**
* 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);
...
}
订阅控制包
1.mqtt规范
‘3.8.3订阅负载’
2.数据结构
- 主题过滤器:订阅选项
- 数据类型
- 主题过滤器:UTF-8编码
- 订阅选项:字节
3.解码流程
4.代码片段
实验代码入口文件ExampleParsePayLoad.java
详细解析过程参见代码库中的HarveyDebug.java
文件,方法名为:parsePayload()
/**
* 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++;
}
...
}
取消订阅、发布控制包
依据本篇文章前两个类型的分析过程和实验代码,可自行尝试解码一下控制包
- 上一篇:用Compose画一个Q弹的团团圆圆
- 下一篇:安卓自定义定时通知实现
- 程序开发学习排行
-
- 1鸿蒙HarmonyOS:Web组件网页白屏检测
- 2HTTPS协议是安全传输,为啥还要再加密?
- 3HarmonyOS鸿蒙应用开发——数据持久化Preferences
- 4记解决MaterialButton背景颜色与设置值不同
- 5鸿蒙HarmonyOS实战-ArkUI组件(RelativeContainer)
- 6鸿蒙HarmonyOS实战-ArkUI组件(Stack)
- 7[Android][NDK][Cmake]一文搞懂Android项目中的Cmake
- 8Android广播如何解决Sending non-protected broadcast问题
- 9鸿蒙HarmonyOS实战-ArkUI组件(mediaquery)
- 最近发表
-
- WooCommerce最好的WordPress常用插件下载博客插件模块的相关产品
- 羊驼机器人最好的WordPress常用插件下载博客插件模块
- IP信息记录器最好的WordPress常用插件下载博客插件模块
- Linkly for WooCommerce最好的WordPress常用插件下载博客插件模块
- 元素聚合器Forms最好的WordPress常用插件下载博客插件模块
- Promaker Chat 最好的WordPress通用插件下载 博客插件模块
- 自动更新发布日期最好的WordPress常用插件下载博客插件模块
- WordPress官方最好的获取回复WordPress常用插件下载博客插件模块
- Img to rss最好的wordpress常用插件下载博客插件模块
- WPMozo为Elementor最好的WordPress常用插件下载博客插件模块添加精简版