【MQTT】在Windows下搭建MQTT服務器
1、參考:https://blog.csdn.net/yannanxiu/article/details/52703946
另外可參考:https://blog.csdn.net/itas109/article/details/78873257
https://blog.csdn.net/qq_29350001/article/details/77062310
MQTT簡介
MQ 遙測傳輸 (MQTT) 是輕量級基於代理的發布/訂閱的消息傳輸協議,設計思想是開放、簡單、輕量、易於實現。這些特點使它適用於受限環境。該協議的特點有:
- 使用發布/訂閱消息模式,提供一對多的消息發布,解除應用程序耦合。
- 對負載內容屏蔽的消息傳輸。
- 使用 TCP/IP 提供網絡連接。
- 小型傳輸,開銷很小(固定長度的頭部是 2 字節),協議交換最小化,以降低網絡流量。
- 使用 Last Will 和 Testament 特性通知有關各方客戶端異常中斷的機制。
- 有三種消息發布服務質量:
- “至多一次”,消息發布完全依賴底層 TCP/IP 網絡。會發生消息丟失或重復。這一級別可用於如下情況,環境傳感器數據,丟失一次讀記錄無所謂,因為不久后還會有第二次發送。
- “至少一次”,確保消息到達,但消息重復可能會發生。
- “只有一次”,確保消息到達一次。這一級別可用於如下情況,在計費系統中,消息重復或丟失會導致不正確的結果。
前言
最近在項目中要使用MQTT協議,需要搭建一個MQTT服務器來進行調試,在網絡上找了一天,找到的大多數都是MQTT客戶端,最后發現這篇博客寫的教程可以使用,特此記錄。
尋找過程
在尋找MQTT服務器的過程中,我發現的Mosquitto是一款「An Open Source MQTT v3.1/v3.1.1 Broker」——開源的MQTT代理服務器,其下也有Windows的安裝包。

但是我使用的是Win10 64位系統,這兩個都下載安裝后不是報錯就是缺少dll文件,不能使用。
最后參考了前面博客說的,搭建了Apollo服務器,這里使用的Apollo 1.7.1。
- 官網:http://activemq.apache.org/index.html
- 下載地址:http://activemq.apache.org/apollo/download.html
- 快速開始教程:http://activemq.apache.org/apollo/documentation/getting-started.html
搭建MQTT服務器
使用Apollo搭建MQTT服務器步驟:
- 下載Apollo服務器並解壓,在CMD環境運行其工作目錄下的
...\bin\apollo.cmd,命令后面帶上參數「create mybroker」,創建服務器實例。這里需要Java環境,系統環境變量下要有JAVA_HOME。 - 創建實例之后會在bin目錄下生成mybroker文件夾,其中
...\etc\apollo.xml文件下是配置服務器信息的文件,...\etc\users.properties文件包含連接MQTT服務器時用到的用戶名和密碼,初始默認帳號是admin,密碼password; - 進入
...\mybroker\bin\目錄,在CMD輸入命令「apollo-broker.cmd run」,可以使用TAB鍵自動補全,運行后輸出信息如下:

其中我們要留意的:
MQTT服務器TCP連接端口:tcp://0.0.0.0:61613
后台Web管理頁面:https://127.0.0.1:61681/或http://127.0.0.1:61680/
登錄服務器后,如果MQTT服務器有客戶端連接,后台會顯示如下

Python的MQTT客戶端
在Python環境下有MQTT客戶端包——paho-mqtt。
安裝命令
pip install paho-mqtt
客戶端代碼清單
下面是MQTT客戶端代碼清單
有誤:
-
import paho.mqtt.client as mqtt
-
-
def on_connect(client, userdata, flags, rc):
-
print( "Connected with result code "+str(rc))
-
-
client.subscribe( "lettuce")
-
-
def on_message(client, userdata, msg):
-
print(msg.topic+ " "+str(msg.payload))
-
-
client = mqtt.Client()
-
client.username_pw_set( "admin", "password") # 必須設置,否則會返回「Connected with result code 4」
-
client.on_connect = on_connect
-
client.on_message = on_message
-
-
HOST = "127.0.0.1"
-
-
client.connect(HOST, 61613, 60)
-
client.loop_forever()

-
注意,client_id是必須的,並且是唯一的。否則可能會出現如下錯誤:
[WinError 10054] 遠程主機強迫關閉了一個現有的連接。
- 改正:
-
-
#-*- coding:utf-8 -*-
-
import paho.mqtt.client as mqtt
-
import time
-
HOST = "127.0.0.1"
-
PORT = 61613
-
'''
-
The callback for when the client receives a CONNACK response from the server.
-
客戶端接收到服務器端的確認連接請求時,回調on_connect
-
服務端發送CONNACK報文響應從客戶端收到的CONNECT報文。
-
服務端發送給客戶端的第一個報文必須是CONNACK [MQTT-3.2.0-1]
-
'''
-
def on_connect(client,userdata,flags,rc):
-
print ("Connected with result code"+str(rc))
-
'''
-
Subscribing in on_connect() means that if we lose the connection and
-
reconnect then subscriptions will be renewed(恢復、續訂).
-
'''
-
client.subscribe( "huan")#訂閱主題
-
-
'''
-
The callback for when a PUBLISH message is received from the server.
-
客戶端接收到服務器向其傳輸的消息時,回調on_message
-
PUBLISH控制報文是指從客戶端向服務端或者服務端向客戶端傳輸一個應用消息。
-
'''
-
def on_message(client,userdata,msg):
-
print (msg.topic+" "+msg.payload.decode("utf-8"))
-
-
def client_loop():
-
'''
-
注意,client_id是必須的,並且是唯一的。否則可能會出現如下錯誤:
-
[WinError 10054] 遠程主機強迫關閉了一個現有的連接。
-
'''
-
client_id=time.strftime( '%Y%m%d%H%M%S',time.localtime(time.time()))
-
client=mqtt.Client(client_id) #Client_id 不能重復,所以使用當前時間
-
client.username_pw_set( "admin","password")# 必須設置,否則會返回「Connected with result code 4」
-
client.on_connect=on_connect
-
client.on_message=on_message
-
-
'''
-
擁塞回調:處理網絡流量,調度回調和重連接。
-
Blocking call that processes network traffic, dispatches callbacks and
-
handles reconnecting.
-
Other loop*() functions are available that give a threaded interface and a
-
manual interface.
-
'''
-
try:
-
client.connect(HOST, PORT, 60)
-
client.loop_forever()
-
except KeyboardInterrupt:
-
client.disconnect()
-
-
if __name__=='__main__':
-
client_loop()
-
-
-
-
-
發布消息代碼
下面是往MQTT服務器發布消息的代碼
:
-
import paho.mqtt.publish as publish
-
-
HOST = "127.0.0.1"
-
-
publish.single( "lettuce", "payload", hostname=HOST, port=61613,
-
auth={ 'username': "admin", 'password':"password"})
改正:
-
import paho.mqtt.publish as publish
-
import time
-
-
HOST= "127.0.0.1"
-
PORT= 61613
-
-
def on_connect(client,userdata,flags,rc):
-
print ("Connected with result code"+str(rc))
-
client.subscribe( "huan")
-
def on_message(client,userdata,msg):
-
print (msg.topic+" "+msg.payload.decode("utf-8"))
-
if __name__=='__main__':
-
client_id=time.strftime( '%Y%m%d%H%M%S',time.localtime(time.time()))
-
# client = mqtt.Client(client_id) # ClientId不能重復,所以使用當前時間
-
# client.username_pw_set("admin", "123456") # 必須設置,否則會返回「Connected with result code 4」
-
# client.on_connect = on_connect
-
# client.on_message = on_message
-
# client.connect(HOST, PORT, 60)
-
# client.publish("test", "你好 MQTT", qos=0, retain=False) # 發布消息
-
publish.single( "huan","您好,MQTT",qos=1,hostname=HOST,port=PORT,client_id=client_id,auth={'username':"admin",'password':"password"})
更新
2017年7月28日更新:
最近發現了一款比較好的開源MQTT服務器:EMQ。Linux下部署教程可以參考這篇文章:EMQ初體驗——在CentOS7上部署MQTT服務器
Windows下部署可以到官網查閱相關資料。
2017年8月15日更新:
注意:后台Web管理頁面被設置為只能本地訪問,如果想用其他主機訪問該管理頁面,需要修改「http://127.0.0.1:61680/」為「http://0.0.0.0:61680/」。
相關配置文件:apache-apollo-1.7.1\bin\mybroker\etc\apollo.xml,大約61行:
-
<web_admin bind="http://127.0.0.1:61680"/>
-
<web_admin bind="https://127.0.0.1:61681"/>
-

