lwIP MQTT 心跳 Bug 分析與修復

一、背景

? ? ? ?在使用 lwIP 內置 MQTT 客戶端時,如果你用的是 2.2.0 之前的版本,很可能會遇到一個惱人的問題:客戶端和服務器正常連接,但一段時間后 會話被 broker 踢掉

比如常見的現象:

  • Mosquitto / EMQX 日志顯示客戶端超時斷開。

  • lwIP 端沒有主動調用 mqtt_disconnect(),卻突然進入了 MQTT_DISCONNECTED 狀態。

  • 配置的 keep-alive 時間是 60s,但實際上 90s 左右就會掉線。

????????經過排查,這其實是 心跳(keep-alive)定時邏輯的 bug。下面來分析一下原因,并給出解決方法

二、問題現象

????????在 lwIP 2.1.x 的 mqtt.c 里,心跳定時邏輯在 mqtt_cyclic_timer() 中實現

if (client->keep_alive > 0) {client->server_watchdog++;if ((client->server_watchdog * MQTT_CYCLIC_TIMER_INTERVAL) > (client->keep_alive +             client->keep_alive / 2)) {mqtt_close(client, MQTT_CONNECT_TIMEOUT);restart_timer = 0;}/* keep-alive 超時檢測 */if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= client->keep_alive) {// 發送心跳包 PINGREQmqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0, 0);client->cyclic_tick = 0;} else {client->cyclic_tick++;}
}

????????看似合理,但這里有個細節:

  • 只有在 else 分支中才會執行 cyclic_tick++

  • 如果進入 if (...) 發送了心跳包,就會直接 cyclic_tick = 0,漏掉了一次累加。

結果就是:

  • 心跳計數器實際觸發頻率比預期低。

  • PINGREQ 的發送比配置的 keep-alive 更晚。

  • Broker 端在 1.5 倍 keep-alive 沒收到心跳時,就會斷開連接。

三、解決方法

????????只需要在進入分支判斷之前,提前增加一次 cyclic_tick

client->cyclic_tick++; // 修復點:每個周期都先自增
if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= client->keep_alive) {mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0, 0);client->cyclic_tick = 0;
} else {client->cyclic_tick++;
}

???這樣就保證了:

  • 每次定時器調用,cyclic_tick 都會+1。

  • 不會出現“少算一次”的情況。

  • 心跳嚴格按照配置的 keep-alive 周期發送。

四、結論

  • lwIP 2.1.x 版本的 MQTT 實現存在心跳 bug,導致 PINGREQ 延遲發送,broker 判定超時。

  • 原因在于 cyclic_tick++ 的位置不對,導致計數器漏算。

  • 解決辦法:在 lwIP 2.2.0 中,官方已經調整了 mqtt_cyclic_timer() 的邏輯,把 cyclic_tick 的自增位置放到固定地方,避免了這個 bug。因此,如果你的項目允許,推薦直接升級 lwIP 到 ≥ 2.2.0。如果受限于平臺或歷史代碼,直接修改 mqtt.c 中的計數邏輯也能解決問題。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/97214.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/97214.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/97214.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Golang 面試題「中級」

以下是 100 道 Golang 中級面試題及答案,涵蓋并發編程、內存管理、接口實現、標準庫深入應用等核心知識點: 一、并發編程基礎與進階問題:Golang 的 GPM 調度模型中,G、P、M 分別代表什么?它們的協作關系是怎樣的&#…

沃爾瑪AI系統Wally深度拆解:零售業庫存周轉提速18%,動態定價爭議與員工轉型成熱議點

最近去沃爾瑪購物,發現以前總斷貨的那款早餐麥片居然常年擺在最顯眼的貨架上,而且價格每周末都會微調——這可不是巧合,背后藏著零售業最硬核的AI操作。沃爾瑪去年推出的智能系統Wally,正悄悄改變著我們買東西的體驗和商家的運營邏…

AutoDL算力云上傳文件太慢了如何解決?

----------------------------------------------------------------------------------------------- 這是我在我的網站中截取的文章,有更多的文章歡迎來訪問我自己的博客網站rn.berlinlian.cn,這里還有很多有關計算機的知識,歡迎進行留言或…

【智慧城市】2025年中國地質大學(武漢)暑期實訓優秀作品(2):智慧城市西安與一帶一路

PART 01 項目背景01政策與時代背景近年來,隨著科技的飛速發展和政策的積極推動,我國新型智慧城市建設取得了顯著成效。在“十四五”國家信息化規劃中,明確提出要打造智慧高效的城市治理體系,推動城市管理精細化、服務智能化。同時…

MySQL數據庫精研之旅第十四期:索引的 “潛規則”(上)

專欄:MySQL數據庫成長記 個人主頁:手握風云 目錄 一、索引簡介 1.1. 索引是什么 1.2. 為什么需要索引 二、索引應該選擇哪種數據結構 2.1. Hash 2.2. 二叉搜索樹 2.3. N叉樹 2.4. B樹 三、MySQL中的頁 3.1. 為什么要使用頁 3.2. 頁文件頭和頁…

架構設計——云原生與分布式系統架構

** 云原生與分布式系統架構** 5.1 云選型策略:多云、混合云還是單云?如何決定? “上云”已無需討論,但“上什么云”是第一個戰略決策。單云(Single Cloud)策略: 描述: 將全部資源集中…

Python圖片轉WebP常用庫推薦:Pillow、Wand、cv2

摘要 Python轉換圖片為WebP,Pillow最推薦:安裝簡單(pip install pillow)、使用方便,代碼示例顯示處理RGBA轉RGB等細節,適合多數場景;Wand功能更強基于ImageMagick,適合需高級處理的場…

Android WPS Office 18.20

WPS Office是一款集Word,PDF,Sheet,PowerPoint,表格,文檔,云存儲,模板庫和在線編輯與共享于一體的多功能免費辦公套件。它提供類似于Microsoft Office的功能,包括文字處理、表格編輯…

Elasticsearch核心配置與性能優化

以下是Elasticsearch(ES)的 核心配置項 及 性能優化措施,涵蓋硬件、系統、ES配置、索引設計等關鍵方面,幫助提升集群穩定性與查詢性能:一、硬件與系統層優化內存分配 堆內存(Heap Size)&#xf…

【谷歌瀏覽器】瀏覽器實用自用版——谷歌瀏覽器(Google Chrome)離線純凈版安裝 官方版無任何捆綁及廣告 【離線安裝谷歌瀏覽器】

經常上網的朋友們肯定深有體會:如今不少瀏覽器動不動就彈廣告、塞插件,用起來簡直是折磨。面對這些“全家桶”式捆綁,大家都渴望能找到一款干凈、簡潔、無打擾的瀏覽器——這時候,Google Chrome(谷歌瀏覽器&#xff09…

2025年滲透測試面試題總結-39(題目+回答)

安全領域各種資源,學習文檔,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具,歡迎關注。 目錄 3. SAST(靜態應用安全測試) 4. IAST(交互式應用安全測試) …

網站測試報告:WEB應用反CSRF的本質與防御機制

CSRF (跨站請求偽造) 本質: 攻擊者誘騙已登錄目標站點的用戶,在不知情的情況下提交一個惡意請求。該請求利用用戶瀏覽器中已存儲的認證信息(如Cookie、Session),以該用戶的身份執行未授權的操作(如修改密碼…

2025年9月計算機二級C++語言程序設計——選擇題打卡Day10

備考計算機二級 C 程序設計考試&#xff0c;選擇題是不容忽視的重要部分。 今天為大家帶來 10 道難點選擇題&#xff0c;聚焦繼承、多態等核心難點&#xff0c;助力提升解題精度。 1、有如下程序&#xff1a; #include<iostream> using namespace std; class Base { pub…

Formdata表單數據提交

前言&#xff1a;在表單數據提交中&#xff0c;常常除了字符串拼接的方式傳給后端&#xff0c;一般可能還需要使用Fromdata的格式包裝所要提交的表單數據傳遞。常用場景&#xff1a;表單數據提交一、Formdata的優勢使用 FormData 主要是因為它有兩個獨特優勢&#xff1a;能輕松…

React Native 初體驗

前言 最近公司需要移植一個應用到 iOS 端&#xff0c;本來想要嘗試 uniapp 的新架構 uniapp-x 的&#xff0c;折騰兩天放棄了&#xff0c;選擇了 React Native。 原因&#xff1a; HbuilderX 中的 uniapp-x 模版過于臃腫&#xff0c;夾雜很多不需要的東西&#xff08;可能是…

自動駕駛中的傳感器技術36——Lidar(11)

本章節重點介紹和FMCWOPA Lidar強相關的硅光技術。 1、硅光技術概述&#xff08;Silicon Photonics&#xff09; 硅光技術主要是用在光通信中&#xff0c;利用硅作為光學介質&#xff0c;通過光傳輸和處理數據。與依賴電子進行數據傳輸的傳統電子電路不同&#xff0c;硅光子學…

MapStruct用法和實踐

一、MapStruct 用法1. 嵌套對象深度映射&#xff08;Deep Mapping&#xff09;// 源對象 public class User {private Address address;// getter/setter }public class Address {private String city;private String street; }// 目標對象 public class UserDTO {private Stri…

設計模式相關面試題

寫在前面 &#x1f525;我把后端Java面試題做了一個匯總&#xff0c;有興趣大家可以看看&#xff01;這里&#x1f449; ??在反復復習面試題時&#xff0c;我發現不同資料的解釋五花八門&#xff0c;容易造成概念混淆。尤其是很多總結性的文章和視頻&#xff0c;要么冗長難…

訪問者設計模式

訪問者設計模式是一種行為模式&#xff0c;允許您向現有對象結構添加新作&#xff0c;而無需修改其類。 它通過允許您將算法與其作的對象分開來實現這一點。 它在以下情況下特別有用&#xff1a; 您有一個復雜的對象結構&#xff08;如 AST、文檔或 UI 元素&#xff09;&#x…

Linux_用 `ps` 按進程名過濾線程,以及用 `pkill` 按進程名安全殺進程

用 ps 按進程名過濾線程&#xff0c;以及用 pkill 按進程名安全殺進程摘要&#xff1a; 過濾線程信息&#xff1a;教你用 ps -C、pgrepps 等多種姿勢&#xff0c;既精準又避免誤殺。按名字殺進程&#xff1a;用 pkill 一把梭&#xff0c;優雅還是強殺隨你選&#xff0c;附帶“先…