MQTT入门(3)- 分析报文Packet

本文介绍了MQTT协议的基本报文结构,包括固定报头、可变报头和有效载荷,并详细解析了控制头部和连接标志等关键字段。通过Wireshark抓包展示了常见的连接、发布、订阅和断开连接等报文实例。
既然MQTT是一个通信协议,就有必要看看在通信时的packet报文信息,有助于对协议自身的理解。

MQTT是一个二进制协议,所以报文中的数据都是字节码而不是文字。

而且它采用 command 和 command acknowledgement 成对实现通信。

[b](1)报文分析[/b]

[b]标准的MQTT报文结构[/b]
主要分为三部分:固定报头(Fixed Header)、可变报头(Variable Header)、有效载荷(Payload)
其中固定报头为2个字节,一定会存在,其他部分可以没有。
[img]http://dl2.iteye.com/upload/attachment/0128/3749/b9b64eb7-5bf8-3d21-9c1a-e196be47e236.png[/img]

[b]最小报文[/b]
包含两个字段:控制头部、报头长度
[img]http://dl2.iteye.com/upload/attachment/0128/3751/985b2bbb-da01-3179-8eca-efe37e3f7f80.png[/img]

[b]控制头部[/b]
包含两个字段:消息类型、标志位
[img]http://dl2.iteye.com/upload/attachment/0128/3755/bb2dfe40-2dc0-3b81-bdcc-542208ec0ece.png[/img]

[b]可变报头[/b]
包含四个字段:协议名、协议级别、连接标志、保持连接
[img]http://dl2.iteye.com/upload/attachment/0128/3755/bb2dfe40-2dc0-3b81-bdcc-542208ec0ece.png[/img]

[b]连接标志[/b]
包含以下八个字段:
第0位:保留标志位
第1位:清理会话标志
第2位:遗嘱标志
第3,4位:QoS标志
第5位:遗嘱保留Retain标志
第6位:密码
第7位:用户名
[img]h
char *mqtt_node_add(struct ubus_call *call, struct mqtt_cloud_ctx *mqtt_cloud, struct mqtt_node_value_s *mqtt_node_value, int mqttChannel) { int backofftime = 0; int backoffcount = 0; int got_ack_time = GOT_REPLY_STATE_INIT; if(!mqtt_cloud || !mqtt_node_value || !mqtt_node_value->suffixPublishTopic) { return NULL; } if(mqtt_node_value->childTopic && !mqtt_node_value->childDevId) { return NULL; } struct mqtt_node_s *mqtt_node = NULL, *nmqtt_node = NULL; /* find the same service */ if (mqtt_node_value->service_path) { list_for_each_entry_safe(mqtt_node, nmqtt_node, &mqtt_cloud->mqtt_handle, list) { if(!strcmp(mqtt_node_value->service_path, mqtt_node->servicePath)) { if ((!mqtt_node_value->childDevId && !mqtt_node->childDevId) || (mqtt_node_value->childDevId && mqtt_node->childDevId && !strcmp(mqtt_node_value->childDevId, mqtt_node->childDevId))) { DBG_DBG("find old mqtt node with service: %s\n", mqtt_node_value->service_path); #if 1 backofftime = mqtt_node->backofftime; backoffcount = mqtt_node->backoffcount; got_ack_time = mqtt_node->got_ack_time; uloop_timeout_cancel(&mqtt_node->nodeTmo); list_del(&mqtt_node->list); mqtt_node_free(mqtt_node, NULL, 0, NULL); #else return mqtt_node->clientToken; #endif } } } } mqtt_node = malloc(sizeof(struct mqtt_node_s)); memset(mqtt_node, 0, sizeof(struct mqtt_node_s)); INIT_LIST_HEAD(&mqtt_node->list); mqtt_node->nodeState = MQTT_NODE_STATE_INIT; mqtt_node->nodePublishType = mqtt_node_value->nodePublishType; mqtt_node->mqttChannel = mqttChannel; /*退避机制参数*/ mqtt_node->backoffcount = backoffcount; mqtt_node->backofftime = backofftime; mqtt_node->got_ack_time = got_ack_time; mqtt_node->packType = MQTT_PACKET_TYPE_PUBLISH; mqtt_node->dup = 0; mqtt_node->qos = MQTT_QOS_1; mqtt_node->retain = 0; mqtt_node->packetId = mqtt_get_packet_id(mqtt_cloud); if (NULL == mqtt_node_value->prePublishTopic) { snprintf(mqtt_node->topicName, sizeof(mqtt_node->topicName), "$tpiot/things/%s%s", mqtt_cloud->device.deviceId, mqtt_node_value->suffixPublishTopic); } else { snprintf(mqtt_node->topicName, sizeof(mqtt_node->topicName), "$ext/service/%s/%s/%s", mqtt_node_value->prePublishTopic, mqtt_cloud->device.deviceId, mqtt_node_value->suffixPublishTopic); } if (mqtt_node_value->service_path) { snprintf(mqtt_node->servicePath, sizeof(mqtt_node->servicePath), "%s", mqtt_node_value->service_path); } mqtt_node->reqTimeOutTime = mqtt_cloud->reqAckTimeOut; mqtt_node->reqTimeOutCount = mqtt_cloud->reqAckTimeOutCount; mqtt_node->nodeTmo.cb = mqtt_node_tmo; mqtt_node->nodeSurvivalTime = 10 * ONE_SECOND_MS; if(mqtt_node_value->clientToken) { snprintf(mqtt_node->clientToken, sizeof(mqtt_node->clientToken), "%s", mqtt_node_value->clientToken); } else { mqtt_cloud_generate_client_token(mqtt_node->clientToken, sizeof(mqtt_node->clientToken), mqtt_cloud->device.deviceMac, mqtt_node->packetId); } if(mqtt_node_value->payload && mqtt_node_value->payloadLen > 0) { mqtt_node->payloadData = strdup2(mqtt_node->payloadData, mqtt_node_value->payload); mqtt_node->payloadDataLen = mqtt_node_value->payloadLen; } mqtt_node->status = ERROR_MQTT_OK; mqtt_node->data = NULL; mqtt_node->childTopic = mqtt_node_value->childTopic; mqtt_node->childDevId = strdup2(mqtt_node->childDevId, mqtt_node_value->childDevId); mqtt_node->childDev = mqtt_node_value->childDev; mqtt_node->nodeOption = mqtt_node_value->nodeOption; if(mqtt_node_value->childTopic) { memset(mqtt_node->topicName, 0, sizeof(mqtt_node->topicName)); snprintf(mqtt_node->topicName, sizeof(mqtt_node->topicName), "$tpiot/things/%s%s", mqtt_node_value->childDevId, mqtt_node_value->suffixPublishTopic); } mqtt_node->cb = mqtt_node_value->cb ? mqtt_node_value->cb : mqtt_msg_default_cb; mqtt_node->call = call; mqtt_node->priv = mqtt_cloud; if(mqttChannel == MQTT_CHANNEL_TAPO) { list_add_tail(&mqtt_node->list, &mqtt_cloud->mqtt_handle); } #ifdef ENABLE_MATTER_CONTROLLER else if(mqttChannel == MQTT_CHANNEL_MATTER) { list_add_tail(&mqtt_node->list, &mqtt_cloud->mqtt_matter.mqtt_handle); } #endif uloop_timeout_set(&mqtt_node->nodeTmo, 10); return mqtt_node->clientToken; } 梳理代码逻辑。
最新发布
12-12
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值