基于python实现MQTT发布订阅过程原理解析


Posted in Python onJuly 27, 2020

MQTT简介

MQTT 全称为 Message Queuing Telemetry Transport(消息队列遥测传输)是一种基于发布/订阅范式的“轻量级”消息协议。该协议构建于TCP/IP协议上。

MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。

其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。

MQTT特点

1、使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合。该协议需要客户端和服务端,而协议中主要有三种身份:发布者(Publisher)、代理(Broker,服务器)、订阅者(Subscriber)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,而消息发布者可以同时是订阅者,实现了生产者与消费者的脱耦;

2、对负载内容屏蔽的消息传输;

3、使用 TCP/IP 提供网络连接;

4、有三种消息发布服务质量:

  • “至多一次”,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。
  • “至少一次”,确保消息到达,但消息重复可能会发生。
  • “只有一次”,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。

5、小型传输,开销很小(固定长度的头部是 2 字节),协议交换最小化,以降低网络流量;

6、使用 Last Will 和 Testament 特性通知有关各方客户端异常中断的机制。

原理

基于python实现MQTT发布订阅过程原理解析

MQTT协议有三种身份:发布者、代理、订阅者,发布者和订阅者都为客户端,代理为服务器,同时消息的发布者也可以是订阅者(为了节约内存和流量发布者和订阅者一般都会定义在一起)。

MQTT传输的消息分为主题(Topic,可理解为消息的类型,订阅者订阅后,就会收到该主题的消息内容(payload))和负载(payload,可以理解为消息的内容)两部分。

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去实现,遥感数据、

汽车检测数据、智能家居、智慧城市、医疗医护都具有应用场景。

客户端

#!/usr/bin/env python 
# encoding: utf-8 
""" 
@version: v1.0 
@author: W_H_J 
@license: Apache Licence 
@contact: 415900617@qq.com 
@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)
client

服务端

#!/usr/bin/env python 
# encoding: utf-8 
""" 
@version: v1.0 
@author: W_H_J 
@license: Apache Licence 
@contact: 415900617@qq.com 
@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()

server

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
跟老齐学Python之画圈还不简单吗?
Sep 20 Python
对于Python中线程问题的简单讲解
Apr 03 Python
Python+Selenium+PIL+Tesseract自动识别验证码进行一键登录
Sep 20 Python
解决Python pandas df 写入excel 出现的问题
Jul 04 Python
python pcm音频添加头转成Wav格式文件的方法
Jan 09 Python
Python替换月份为英文缩写的实现方法
Jul 15 Python
python实现证件照换底功能
Aug 20 Python
OpenCV里的imshow()和Matplotlib.pyplot的imshow()的实现
Nov 25 Python
Python3 搭建Qt5 环境的方法示例
Jul 16 Python
Python 必须了解的5种高级特征
Sep 10 Python
Python用access判断文件是否被占用的实例方法
Dec 17 Python
Python绘画好看的星空图
Mar 17 Python
Windows 平台做 Python 开发的最佳组合(推荐)
Jul 27 #Python
Python性能分析工具py-spy原理用法解析
Jul 27 #Python
python下载的库包存放路径
Jul 27 #Python
Python基础教程之输入输出和运算符
Jul 26 #Python
使用python求斐波那契数列中第n个数的值示例代码
Jul 26 #Python
利用Python实现斐波那契数列的方法实例
Jul 26 #Python
3分钟看懂Python后端必须知道的Django的信号机制
Jul 26 #Python
You might like
PHP 实现的将图片转换为TXT
2015/10/21 PHP
使用ucenter实现多站点同步登录的讲解
2019/03/21 PHP
jQuery 注意事项 与原因分析
2009/04/24 Javascript
multiSteps 基于Jquery的多步骤滑动切换插件
2011/07/22 Javascript
javascript同页面多次调用弹出层具体实例代码
2013/08/16 Javascript
对js关键字命名的疑问介绍
2014/04/25 Javascript
jQuery链使用指南
2015/01/20 Javascript
js实现可折叠展开的手风琴菜单效果
2015/09/07 Javascript
Jquery实现遮罩层的简单实例(就是弹出DIV周围都灰色不能操作)
2016/07/14 Javascript
jQuery实现的网页换肤效果示例
2016/09/20 Javascript
Vue.JS项目中5个经典Vuex插件
2017/11/28 Javascript
Thinkjs3新手入门之如何使用静态资源目录
2017/12/06 Javascript
JavaScript Canvas实现验证码
2020/08/02 Javascript
jQuery实现简单飞机大战
2020/07/05 jQuery
JavaScript实现10秒后再次获取验证码
2020/12/02 Javascript
python数据结构之二叉树的统计与转换实例
2014/04/29 Python
Python中__new__与__init__方法的区别详解
2015/05/04 Python
python制作一个桌面便签软件
2015/08/09 Python
Python装饰器入门学习教程(九步学习)
2016/01/28 Python
Python正确重载运算符的方法示例详解
2017/08/27 Python
使用python实现mqtt的发布和订阅
2019/05/05 Python
Python 把序列转换为元组的函数tuple方法
2019/06/27 Python
python 利用浏览器 Cookie 模拟登录的用户访问知乎的方法
2019/07/11 Python
基于python3 pyQt5 QtDesignner实现窗口化猜数字游戏功能
2019/07/15 Python
Python 实现毫秒级淘宝抢购脚本的示例代码
2019/09/16 Python
基于HTML5+tracking.js实现刷脸支付功能
2020/04/16 HTML / CSS
澳大利亚第一的设计师礼服租赁网站:GlamCorner
2017/08/13 全球购物
美国女性奢华品牌精品店:INTERMIX
2017/10/12 全球购物
德国高尔夫商店:Golfshop.de
2019/06/22 全球购物
购房个人委托书范本
2014/10/11 职场文书
2015年社区工作总结
2015/04/08 职场文书
OpenCV-Python实现人脸美白算法的实例
2021/06/11 Python
详解Go语言运用广度优先搜索走迷宫
2021/06/23 Python
MySQL高速缓存启动方法及参数详解(query_cache_size)
2021/07/01 MySQL
Python requests用法和django后台处理详解
2022/03/19 Python
 分享一个Python 遇到数据库超好用的模块
2022/04/06 Python