劉國梅
(鄭州航空工業(yè)管理學(xué)院 智能工程學(xué)院,河南 鄭州 450046)
物聯(lián)網(wǎng)系統(tǒng)涉及產(chǎn)品種類繁多,各產(chǎn)品之間千差萬別,設(shè)備接入難度及成本是制約物聯(lián)網(wǎng)系統(tǒng)應(yīng)用的痛點(diǎn)之一[1]。MQTT協(xié)議獨(dú)特的消息傳遞機(jī)制以及低開銷、低帶寬占用的特性,使其非常適合于物聯(lián)網(wǎng)領(lǐng)域云邊通信的應(yīng)用場(chǎng)景[2],是目前物聯(lián)網(wǎng)應(yīng)用中最常用的通信協(xié)議之一,國內(nèi)外很多物聯(lián)網(wǎng)平臺(tái)的解決方案中都采用MQTT作為一種主流的數(shù)據(jù)通信協(xié)議[3]。因此,對(duì)于物聯(lián)網(wǎng)相關(guān)專業(yè)的學(xué)生來說,掌握和理解MQTT協(xié)議非常重要,只有真正掌握MQTT協(xié)議的工作原理、數(shù)據(jù)包結(jié)構(gòu)、消息服務(wù)質(zhì)量等,才能熟練靈活地運(yùn)用MQTT協(xié)議進(jìn)行各種應(yīng)用系統(tǒng)的開發(fā)。
本文在對(duì)MQTT協(xié)議的理論分析基礎(chǔ)上,基于Packet Tracer實(shí)現(xiàn)MQTT協(xié)議工作過程的仿真模擬以及數(shù)據(jù)包的抓取和分析,從而使學(xué)生能夠?qū)QTT協(xié)議及其工作原理有比較深入全面的理解和掌握。
MQTT協(xié)議是一種基于發(fā)布/訂閱(Publish/ Subscribe)模式的輕量級(jí)通信協(xié)議[4]。MQTT協(xié)議中有三種身份,即發(fā)布者(Publisher)、代理服務(wù)器(Broker)、訂閱者(Subscriber),消息的發(fā)布者和訂閱者都是客戶端,它們之間通過代理服務(wù)器交換消息[5]。MQTT傳輸?shù)南⒎譃橹黝}(Topic)和負(fù)載(Payload)兩部分,主題類似于消息的類型,負(fù)載類似于消息的具體內(nèi)容??蛻舳伺c客戶端之間的消息傳輸按主題進(jìn)行[6]。
MQTT協(xié)議中,一個(gè)MQTT數(shù)據(jù)包由固定頭(Fixed header)、可變頭(Variable header)、負(fù)載(Payload)三部分構(gòu)成[7],如圖1所示。固定頭是必須的,可變頭和負(fù)載存在于部分MQTT數(shù)據(jù)包中。
圖1 MQTT數(shù)據(jù)包結(jié)構(gòu)
固定頭表示數(shù)據(jù)包類型及數(shù)據(jù)包的分組類標(biāo)識(shí),其中第一字節(jié)的0~3位是分組類標(biāo)識(shí),RETAIN字段是發(fā)布保留標(biāo)識(shí),QoS字段用于設(shè)置該條消息所需的服務(wù)質(zhì)量等級(jí),DUP字段用于設(shè)置該條消息是否為重發(fā)消息。在不使用標(biāo)識(shí)位的消息類型中,這些分組類標(biāo)識(shí)被作為保留位。4~7位的Message Type字段的值則代表消息的類型,MQTT擁有CONNECT、SUBSCRIBE、PUBLISH等14種不同的消息類型。Remaining Length字段的值則用來表示當(dāng)前消息的剩余長度,包括可變頭和負(fù)載所占的字節(jié)數(shù)。
MQTT協(xié)議通過控制QoS等級(jí)來決定服務(wù)質(zhì)量,QoS等級(jí)分為QoS0、QoS1、QoS2三個(gè)等級(jí),不同的等級(jí)代表了不同的可靠性要求[8],消息服務(wù)質(zhì)量等級(jí)為QoS0時(shí)代表著消息最多到達(dá)一次,為QoS1時(shí)代表著消息至少到達(dá)一次,為QoS2時(shí)代表著消息一定會(huì)到達(dá)且只到達(dá)一次。
基于Packet Tracer仿真環(huán)境構(gòu)建如圖2所示的網(wǎng)絡(luò)仿真結(jié)構(gòu)。在該網(wǎng)絡(luò)結(jié)構(gòu)中,MQTT客戶端MQTT_ Client1通過交換機(jī)Switch1、路由器Router1與代理服務(wù)器MQTT_Broker相連,客戶端MQTT_Client2通過無線接入點(diǎn)Access Point1、交換機(jī)Switch1、路由器Router1與服務(wù)器MQTT_Broker相連,客戶端MQTT_Client3通過移動(dòng)通信網(wǎng)絡(luò)、路由器Router1與服務(wù)器MQTT_Broker相連,整個(gè)系統(tǒng)實(shí)現(xiàn)了異構(gòu)網(wǎng)絡(luò)的互聯(lián)。在此基礎(chǔ)上還需要進(jìn)行網(wǎng)絡(luò)地址規(guī)劃及配置,在路由器Router1上執(zhí)行動(dòng)態(tài)路由協(xié)議,進(jìn)行動(dòng)態(tài)路由配置[9]。
圖2 仿真結(jié)構(gòu)
2.2.1 服務(wù)器MQTT_Broker的程序?qū)崿F(xiàn)
服務(wù)器MQTT_Broker的程序?qū)崿F(xiàn)包括GUI頁面設(shè)計(jì)及Python程序編寫兩部分,其中最主要的是mqttbroker.py文件中實(shí)現(xiàn)的功能,如圖3(a)所示。mqttbroker.py文件中,首先是初始化函數(shù)init()的編寫,init()中啟動(dòng)了一個(gè)TCP Server,偵聽1883端口,調(diào)用回調(diào)函數(shù)on_new_client()加入新客戶端,調(diào)用函數(shù)add_custom_mqtt_pdus()初始化MQTT的協(xié)議數(shù)據(jù)單元(PDU)等。然后是add_custom_mqtt_pdus()函數(shù)的具體實(shí)現(xiàn),在該函數(shù)中定義了MQTT的PDU,共定義了包括MQTT CONNECT、CONNACK、PUBLISH等14種數(shù)據(jù)單元的格式。add_ custom_mqtt_pdus()函數(shù)之后定義了使能服務(wù)函數(shù)enable_service()、禁用服務(wù)函數(shù)disable_service()、添加用戶函數(shù)add_user (username,password)、移除用戶函數(shù)remove_ user(username)等,接著是創(chuàng)建新客戶端回調(diào)函數(shù)on_new_client(client)的具體實(shí)現(xiàn)以及更新注冊(cè)用戶、更新客戶端、更新訂閱信息等函數(shù)的實(shí)現(xiàn),最后是連接狀態(tài)改變回調(diào)函數(shù)on_connection_change(type)以及處理MQTT數(shù)據(jù)包的回調(diào)函數(shù)process_ mqtt_packet(in_packet,pdu_info)的具體實(shí)現(xiàn)。
圖3 程序?qū)崿F(xiàn)
2.2.2 客戶端MQTT_Client的程序?qū)崿F(xiàn)
客戶端MQTT_Client的程序?qū)崿F(xiàn)也包括GUI頁面設(shè)計(jì)及Python程序編寫兩部分,其中最主要的是mqttclient.py程序文件實(shí)現(xiàn)的功能,如圖3(b)所示。mqttclient.py文件中,首先是初始化函數(shù)init()的編寫,init()中創(chuàng)建了一個(gè)TCP客戶端,當(dāng)客戶端連接狀態(tài)改變時(shí)會(huì)調(diào)用回調(diào)函數(shù)on_connection_change,當(dāng)收到PDU數(shù)據(jù)包時(shí)會(huì)調(diào)用回調(diào)函數(shù)process_mqtt_ packet,之后通過add_custom_mqtt_ pdus()函數(shù)完成對(duì)數(shù)據(jù)包PDU的初始化。init()函數(shù)編寫完之后,是add_ custom_mqtt_pdus()函數(shù)的具體實(shí)現(xiàn),然后又定義了connect()、subscribe (topic)、publish(topic,payload,qos)、pingreq()等函數(shù),這些函數(shù)對(duì)應(yīng)著相關(guān)的事件。最后定義了處理MQTT協(xié)議中14種數(shù)據(jù)包的函數(shù)process_mqtt_packet (in_packet,pdu_info),該函數(shù)中對(duì)數(shù)據(jù)包進(jìn)行了封裝,并給出了處理不同操作時(shí)輸出的一些信息。
下面分析仿真MOTT協(xié)議的工作過程及消息服務(wù)質(zhì)量等級(jí)。服務(wù)器MQTT_Broker運(yùn)行之后,三個(gè)MQTT客戶端分別連接到該服務(wù)器,客戶端MQTT_Client3作為訂閱者,可以訂閱相關(guān)主題??蛻舳薓QTT_Client1、MQTT_Client2作為發(fā)布者可以發(fā)布消息,如圖4(a)所示。仿真結(jié)果表明,客戶端MQTT_Client3只能接收其訂閱了相關(guān)主題的消息,如圖4(b)所示,無法接收其沒有訂閱主題的消息,驗(yàn)證了MQTT協(xié)議基于發(fā)布/訂閱的工作模式。另外,從MQTT_Broker的操作日志EventLog中可以清楚地看到MQTT協(xié)議中各種數(shù)據(jù)包的傳輸過程及數(shù)據(jù)包的具體內(nèi)容,更加深入理解不同服務(wù)質(zhì)量等級(jí)的通信時(shí)序及各種數(shù)據(jù)包的傳輸過程。
圖4 仿真結(jié)果
仿真過程中還可以通過抓取數(shù)據(jù)包更加直觀地理解MQTT各種數(shù)據(jù)包結(jié)構(gòu)。首先將Packet Tracer仿真模式從“Realtime mode”切換成“simulation mode”[10]。在數(shù)據(jù)傳輸過程中,單擊“play controls”下的“capture/Forward”按鈕,可以抓取數(shù)據(jù)包。圖5顯示了客戶端MQTT_Client1到交換機(jī)Switch1的“PDU Information at Device:Switch1”,在“Inbound PDU Details”中可以看到,MQTT_Client1到MQTT_Broker之間傳輸?shù)膮f(xié)議數(shù)據(jù)單元(PDU)為MQTT PUBLISH數(shù)據(jù)包,數(shù)據(jù)包第一個(gè)字節(jié)的0~3位為數(shù)據(jù)包的分組類標(biāo)識(shí),第4~7位為數(shù)據(jù)包類型,PUBLISH數(shù)據(jù)包中CONTROL PACKET TYPYE為3,接著是消息的剩余長度,仿真結(jié)果與理論分析一致。
圖5 PUBLISH數(shù)據(jù)包抓取
MQTT協(xié)議是物聯(lián)網(wǎng)中最常用的通信協(xié)議之一,掌握MQTT協(xié)議的工作原理、數(shù)據(jù)包結(jié)構(gòu)、通信服務(wù)質(zhì)量對(duì)于物聯(lián)網(wǎng)系統(tǒng)的開發(fā)應(yīng)用至關(guān)重要。為了能讓學(xué)生更好地理解、掌握相關(guān)內(nèi)容,通過Packet Tracer仿真軟件構(gòu)建網(wǎng)絡(luò)結(jié)構(gòu),配置網(wǎng)絡(luò)連通性,進(jìn)行程序編寫,最終實(shí)現(xiàn)MQTT協(xié)議的仿真,這對(duì)學(xué)生們理解MQTT通信協(xié)議并進(jìn)行有關(guān)MQTT協(xié)議的開發(fā)能夠起到事半功倍的效果。
物聯(lián)網(wǎng)技術(shù)2023年11期