【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"/>
-