# 抓包存档:DC045A49718F MQTT protocol error 风暴 - **文件**: `2026-07-15-DC045A49718F-protocol-error.pcap`(44 包,20s 窗口) - **抓包时间**: 2026-07-15 14:26 左右(设备 14:20 上电后持续复现) - **抓包点**: 腾讯云 159.75.137.141,`tcpdump -i any port 1883 and host 113.91.145.40` - **设备**: DC045A49718F (DLD960GA, hard 1.0 / soft 1.0,新版 event_report 重发固件) ## 现象 设备每 ~1s 被 mosquitto 以 `disconnected due to protocol error` 踢下线, 15 分钟内 80+ 次重连、87 次 initialize 上报。 ## pcap 关键证据(用 `tcpdump -r -nn -ttt -X` 查看) 正常序列先走完: ``` CONNECT (MQTT 3.1.1, client_id=DC045A49718F, u=admin, keepalive=9) → CONNACK → SUBSCRIBE dld960/DC045A49718F/srv → SUBACK → PUBLISH dld960/DC045A49718F/dev {"cmd":"initialize", msg_id:21, ts:393, ...} ← 报文完好 ``` 紧接着设备发出致命包: ``` TCP 段 520 字节 = 前 512 字节全 0x00 + 尾部 8 字节 ASCII "report_c" ``` - `0x00` 不是合法 MQTT 控制报文类型(type 0 保留)→ broker 立即 RST 断连 - RST 后设备仍继续发第二个 520B 全零段(seq 805:1325) ## 诊断 **520 = 512 + 8 → 高度疑似 512B 环形 TX 缓冲区回绕(wrap)处理 bug。** 推测:往 TX 缓冲写 report_config 响应时跨越回绕边界,"report_c" 落在缓冲区 物理尾部,其余部分绕回头部;发送侧却把整块未初始化(全零)缓冲区一次性发出。 本次固件恰好新增了事件待发队列 + 5s 重发机制(V1.04),动过 TX 路径, 建议重点排查: 1. 新待发队列的写指针 / 回绕边界处理 2. 重发定时器与主循环并发 publish 的互斥(两个写者交叉写 TX 流) 3. 发送长度是否误用缓冲区总长而非报文实际长度 ## 顺带实锤的协议违规(固件侧待修) 1. **断线重连后重发事件用了新 msg_id**:msg_id 9/10 内容完全相同 (car_leave ch1 value=48, ts=76),双双入库 → 平台 (dev_serial,msg_id) 去重失效。V1.04 §5.3 条 2:重发必须用相同 msg_id(跨重连也要保持) 2. **ts 字段是上电秒数**(76/393),不是协议约定的 Unix 时间戳 3. keepalive=9s 过于激进(老问题),建议 30~60s ## 平台侧结论(无需改动) event_report 必答闭环工作正常:ack <1s、回显 msg_id、先落库后应答; msg_id 相同的重复包去重有效。重复入库仅发生在固件违规换 msg_id 的场景。