基於MQTT的消息發佈訂閱python實現

簡介:

MQTT 全稱爲 Message Queuing Telemetry Transport(消息隊列遙測傳輸)是一種基於發佈/訂閱範式的“輕量級”消息協議。該協議構建於TCP/IP協議上。MQTT協議是輕量、簡單、開放和易於實現的,這些特點使它適用範圍非常廣泛。在很多情況下,包括受限的環境中,如:機器與機器(M2M)通信和物聯網(IoT)。其在,通過衛星鏈路通信傳感器、偶爾撥號的醫療設備、智能家居、及一些小型化設備中已廣泛使用。

特點:

1、使用發佈/訂閱消息模式,提供一對多的消息發佈,解除應用程序耦合。該協議需要客戶端和服務端,而協議中主要有三種身份:發佈者(Publisher)、代理(Broker,服務器)、訂閱者(Subscriber)。其中,消息的發佈者和訂閱者都是客戶端,消息代理是服務器,而消息發佈者可以同時是訂閱者,實現了生產者與消費者的脫耦;

2、對負載內容屏蔽的消息傳輸;

3、使用 TCP/IP 提供網絡連接;

4、有三種消息發佈服務質量:

  • “至多一次”,消息發佈完全依賴底層 TCP/IP 網絡。會發生消息丟失或重複。這一級別可用於如下情況,環境傳感器數據,丟失一次讀記錄無所謂,因爲不久後還會有第二次發送。
  • “至少一次”,確保消息到達,但消息重複可能會發生。
  • “只有一次”,確保消息到達一次。這一級別可用於如下情況,在計費系統中,消息重複或丟失會導致不正確的結果。

5、小型傳輸,開銷很小(固定長度的頭部是 2 字節),協議交換最小化,以降低網絡流量;

6、使用 Last Will 和 Testament 特性通知有關各方客戶端異常中斷的機制。

原理

1 MQTT協議實現方式

實現MQTT協議需要客戶端和服務器端通訊完成,在通訊過程中,MQTT協議中有三種身份:發佈者(Publish)、代理(Broker)(服務器)、訂閱者(Subscribe)。其中,消息的發佈者和訂閱者都是客戶端,消息代理是服務器,消息發佈者可以同時是訂閱者。

MQTT傳輸的消息分爲:主題(Topic)和負載(payload)兩部分:

  • (1)Topic,可以理解爲消息的類型,訂閱者訂閱(Subscribe)後,就會收到該主題的消息內容(payload);
  • (2)payload,可以理解爲消息的內容,是指訂閱者具體要使用的內容。

2 網絡傳輸與應用消息

MQTT會構建底層網絡傳輸:它將建立客戶端到服務器的連接,提供兩者之間的一個有序的、無損的、基於字節流的雙向傳輸。

當應用數據通過MQTT網絡發送時,MQTT會把與之相關的服務質量(QoS)和主題名(Topic)相關連。

3 MQTT客戶端

一個使用MQTT協議的應用程序或者設備,它總是建立到服務器的網絡連接。客戶端可以:

  • (1)發佈其他客戶端可能會訂閱的信息;
  • (2)訂閱其它客戶端發佈的消息;
  • (3)退訂或刪除應用程序的消息;
  • (4)斷開與服務器連接。

4 MQTT服務器

MQTT服務器以稱爲"消息代理"(Broker),可以是一個應用程序或一臺設備。它是位於消息發佈者和訂閱者之間,它可以:

  • (1)接受來自客戶的網絡連接;
  • (2)接受客戶發佈的應用信息;
  • (3)處理來自客戶端的訂閱和退訂請求;
  • (4)向訂閱的客戶轉發應用程序消息。

5 MQTT協議中的訂閱、主題、會話

一、訂閱(Subscription)

訂閱包含主題篩選器(Topic Filter)和最大服務質量(QoS)。訂閱會與一個會話(Session)關聯。一個會話可以包含多個訂閱。每一個會話中的每個訂閱都有一個不同的主題篩選器。

二、會話(Session)

每個客戶端與服務器建立連接後就是一個會話,客戶端和服務器之間有狀態交互。會話存在於一個網絡之間,也可能在客戶端和服務器之間跨越多個連續的網絡連接。

三、主題名(Topic Name)

連接到一個應用程序消息的標籤,該標籤與服務器的訂閱相匹配。服務器會將消息發送給訂閱所匹配標籤的每個客戶端。

四、主題篩選器(Topic Filter)

一個對主題名通配符篩選器,在訂閱表達式中使用,表示訂閱所匹配到的多個主題。

五、負載(Payload)

消息訂閱者所具體接收的內容。

6 MQTT協議中的方法

MQTT協議中定義了一些方法(也被稱爲動作),來於表示對確定資源所進行操作。這個資源可以代表預先存在的數據或動態生成數據,這取決於服務器的實現。通常來說,資源指服務器上的文件或輸出。主要方法有:

  • (1)Connect。等待與服務器建立連接。
  • (2)Disconnect。等待MQTT客戶端完成所做的工作,並與服務器斷開TCP/IP會話。
  • (3)Subscribe。等待完成訂閱。
  • (4)UnSubscribe。等待服務器取消客戶端的一個或多個topics訂閱。
  • (5)Publish。MQTT客戶端發送消息請求,發送完成後返回應用程序線程。

7 應用場景

因爲它傳輸消息具有異步性(發佈訂閱模式),同時該協議本身的輕量特定,因此可用於輕量級應用,可作爲物聯網的通信組件使用,例如樹莓派上完全可以搭建一個mqtt服務器,當未來智能家居全面普及的時候,家居中的消息通訊都可用此實現,如智能冰箱溫度檢測,房間溫度檢測等信息都能通過mqtt去實現,遙感數據、汽車檢測數據、智能家居、智慧城市、醫療醫護都具有應用場景。

更多介紹 1更多介紹2

python代碼實現 

安裝:pip install paho-mqtt

客戶端代碼

#!/usr/bin/env python  
# encoding: utf-8  
""" 
@version: v1.0 
@author: W_H_J 
@license: Apache Licence  
@contact: [email protected] 
@software: PyCharm 
@file: clicentMqttTest.py 
@time: 2019/2/22 14:19 
@describe: mqtt客戶端
"""
import json
import sys
import os
import paho.mqtt.client as mqtt
import time

sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/' + '..'))
sys.path.append("..")

TASK_TOPIC = 'test'  # 客戶端發佈消息主題

client_id = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
"""
client_id是連接到代理。如果client_id的長度爲零或爲零,則行爲爲由使用的協議版本定義。如果使用MQTT v3.1.1,
那麼一個零長度的客戶機id將被髮送到代理,代理將被髮送爲客戶端生成一個隨機變量。如果使用MQTT v3.1,那麼id將是
隨機生成的。在這兩種情況下,clean_session都必須爲True。如果這在這種情況下不會產生ValueError。
注意:一般情況下如果客戶端服務端啓用兩個監聽那麼客戶端client_id 不能與服務器相同,如這裏用時間"20190222142358"作爲它的id,
如果與服務器id相同,則無法接收到消息
"""
client = mqtt.Client(client_id, transport='tcp')

client.connect("127.0.0.1", 1883, 60)  # 此處端口默認爲1883,通信端口期keepalive默認60
client.loop_start()


def clicent_main(message: str):
    """
    客戶端發佈消息
    :param message: 消息主體
    :return:
    """
    time_now = time.strftime('%Y-%m-%d %H-%M-%S', time.localtime(time.time()))
    payload = {"msg": "%s" % message, "data": "%s" % time_now}
    # publish(主題:Topic; 消息內容)
    client.publish(TASK_TOPIC, json.dumps(payload, ensure_ascii=False))
    print("Successful send message!")
    return True


if __name__ == '__main__':
    msg = "我是一條測試數據!"
    clicent_main(msg)

服務端代碼

#!/usr/bin/env python  
# encoding: utf-8  
""" 
@version: v1.0 
@author: W_H_J 
@license: Apache Licence  
@contact: [email protected] 
@software: PyCharm 
@file: serverMqttTest.py 
@time: 2019/2/22 14:35 
@describe: mqtt 服務端
"""
import json
import sys
import os
import time
import paho.mqtt.client as mqtt
sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/' + '..'))
sys.path.append("..")

REPORT_TOPIC = 'test'  # 主題


def on_connect(client, userdata, flags, rc):
    print('connected to mqtt with resurt code ', rc)
    client.subscribe(REPORT_TOPIC)  # 訂閱主題


def on_message(client, userdata, msg):
    """
    接收客戶端發送的消息
    :param client: 連接信息
    :param userdata: 
    :param msg: 客戶端返回的消息
    :return: 
    """
    print("Start server!")
    payload = json.loads(msg.payload.decode('utf-8'))
    print(payload)


def server_conenet(client):
    client.on_connect = on_connect  # 啓用訂閱模式
    client.on_message = on_message  # 接收消息
    client.connect("127.0.0.1", 1883, 60)  # 鏈接
    # client.loop_start()   # 以start方式運行,需要啓動一個守護線程,讓服務端運行,否則會隨主線程死亡
    client.loop_forever()   # 以forever方式阻塞運行。


def server_stop(client):
    client.loop_stop()  # 停止服務端
    sys.exit(0)


def server_main():
    client_id = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
    client = mqtt.Client(client_id, transport='tcp')
    server_conenet(client)


if __name__ == '__main__':
    # 啓動監聽
    server_main()

Eclipse Paho MQTT 工具下載與安裝(桌面版)

  1. 官網
  2. 安裝教程
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章