【MQTT】MQTT 数据格式---编辑中

目录

MQTT协议详解一

5.2  MQTT可变头

5.3  Payload消息体

MQTT协议讲解

MQTT开发C代码

MQTT 开发笔记(python)

MQTT 向别人介绍的简单教程

2019.05.30 安装新的mysqlclient

2019.05.30django

2019.05.24

2019.05.20安装anaconda (anaconda就是python+多个常用包的集合体)

2019.05.15 下载下来的client 库是动态库.so,要编程静态库。

MQTT服务器

1‘MQTT的局限:

测试工具

安装步骤

测试消息发布/订阅(Pub/Sub)功能


MQTT协议详解一

协议地址:http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html

当然也有PDF版的,百度一下,不过个人感觉不是官网上的字体和排版最舒服。

那么这个协议是用做什么或有什么特色呢?下面是mqtt.org上的首段介绍:

It was designed as an extremely lightweight publish/subscribe messaging transport. It is useful for connections with remote locations where a small code footprint is
required and/or network bandwidth is at a premium. For example, it has been used in sensors communicating to a broker via satellite link, over occasional dial-up connections with healthcare providers, and in a range of home automation and small device scenarios.
It is also ideal for mobile applications because of its small size, low power usage, minimised data packets, and efficient distribution of information to one or many receivers

MQTT是轻量级基于代理的发布/订阅的消息传输协议,它可以通过很少的代码和带宽和远程设备连接。例如通过卫星和代理连接,通过拨号和医疗保健提供者连接,以及在一些自动化或小型设备上,而且由于小巧,省电,协议开销小和能高效的向一和多个接收者传递信息,故同样适用于称动应用设备上。

相信在想深入学习这协议必是奔着解决某个问题而来的,上面给出了适用的场景,我之所以想深入的学习和了解这个协议,理由如下:

1、可以实现手机消息推送(PUSH)

2、协议简单,最小的头部只需2个字节,特别适合于嵌入式中。

3、这是个了解什么是协议绝好的例子。相比于其它复杂的协议例如tcp,http协议,至少说明文档看的下去。

在这里,我以推送为例子说明,虽然现在现成的推送解决方案已经比较成熟,但是这个Repeat ReInvent the Whell还是要做一下,什么都是拿来主义,和搬运工有什么区别。

一、需要的环境:

1、PHP+Apache或Nginx

2、安装开源代理程序Mosquitto,这里用其做为代理服务器,负责连接和分发。

安装方法很简单,Index of /files/   binary是编译好的,source是源码安装需要的(make & make install 就行)

唯 一要配置的就是在解压后的config.mk,安装完后设置文件是mosquitto.conf

当然主要是设置是否支持ssl,还有就是config.mk最下面的安装位置的设定。这里一切默认。

默认启动是绑定的IP是本地IP,端口是1883可以在mosquitto.conf里设置(要去掉前面的#字注释),linux 中 -c 可以指定设置文件并运行

比 如: mosquitto -c /etc/mosquitto.conf

二、协议初解

先说一下整个协议的构造,整体上协议可拆分为:

                    固定头部+可变头部+消息体

协议说白了就是对于双方通信的一个约定,比如传过来一段字符流,第1个字节表示什么,第2个字节表示什么。。。。一个约定。

所以在固定头部的构造如下:

1、MessageType(0和15保留,共占bit个字节)

  1. public $operations=array(

  2. "MQTT_CONNECT"=>1,//请求连接

  3. "MQTT_CONNACK"=>2,//请求应答

  4. "MQTT_PUBLISH"=>3,//发布消息

  5. "MQTT_PUBACK"=>4,//发布应答

  6. "MQTT_PUBREC"=>5,//发布已接收,保证传递1

  7. "MQTT_PUBREL"=>6,//发布释放,保证传递2

  8. "MQTT_PUBCOMP"=>7,//发布完成,保证传递3

  9. "MQTT_SUBSCRIBE"=>8,//订阅请求

  10. "MQTT_SUBACK"=>9,//订阅应答

  11. "MQTT_UNSUBSCRIBE"=>10,//取消订阅

  12. "MQTT_UNSUBACK"=>11,//取消订阅应答

  13. "MQTT_PINGREQ"=>12,//ping请求

  14. "MQTT_PINGRESP"=>13,//ping响应

  15. "MQTT_DISCONNECT"=>14//断开连接

  16. );

    位置:byte 1, bits 7-4。

    相于一个4位的无符号值,类型如下:

    名称流方向描述
    Reserved0不可用保留位
    CONNECT1客户端到服务器客户端请求连接到服务器
    CONNACK2服务器到客户端连接确认
    PUBLISH3双向发布消息
    PUBACK4双向发布确认
    PUBREC5双向发布收到(保证第1部分到达)
    PUBREL6双赂发布释放(保证第2部分到达)
    PUBCOMP7双向发布完成(保证第3部分到达)
    SUBSCRIBE8客户端到服务器客户端请求订阅
    SUBACK9服务器到客户端订阅确认
    UNSUBSCRIBE10客户端到服务器请求取消订阅
    UNSUBACK11服务器到客户端取消订阅确认
    PINGREQ12客户端到服务器PING请求
    PINGRESP13服务器到客户端PING应答
    DISCONNECT14客户端到服务器中断连接
    Reserved15不可用保留位

1.2 标识位

位置:byte 1, bits 3-0。

在不使用标识位的消息类型中,标识位被做为保留位。如果收到无效的标志时,接收端必须关闭网络连接:

数据包标识位Bit 3Bit 2Bit 1Bit 0
CONNECT保留位0000
CONNACK保留位0000
PUBLISHMQTT 3.1.1使用DUP1QoS2QoS2RETAIN3
PUBACK保留位0000
PUBREC保留位0000
PUBREL保留位0000
PUBCOMP保留位0000
SUBSCRIBE保留位0000
SUBACK保留位0000
UNSUBSCRIBE保留位0000
UNSUBACK保留位0000
PINGREQ保留位0000
PINGRESP保留位0000
DISCONNECT保留位0000
  • DUP:发布消息的副本。用来在保证消息的可靠传输,如果设置为 1,则在下面的变长中增加MessageId,并且需要回复确认,以保证消息传输完成,但不能用于检测消息重复发送。
  • QoS:发布消息的服务质量,即:保证消息传递的次数
    • 00:最多一次,即:<=1
    • 01:至少一次,即:>=1
    • 10:一次,即:=1
    • 11:预留
  • RETAIN: 发布保留标识,表示服务器要保留这次推送的信息,如果有新的订阅者出现,就把这消息推送给它,如果设有那么推送至当前订阅者后释放。

2、DUP flag

 其是用来在保证消息传输可靠的,如果设置为1,则在下面的变长头部里多加MessageId,并需要回复确认,保证消息传输完成,但不能用于检测消息重复发送。

3、Qos

主要用于PUBLISH(发布态)消息的,保证消息传递的次数。

00表示最多一次 即<=1

01表示至少一次  即>=1

10表示一次,即==1

11保留后用

4、Retain

 主要用于PUBLISH(发布态)的消息,表示服务器要保留这次推送的信息,如果有新的订阅者出现,就把这消息推送给它。如果不设那么推送至当前订阅的就释放了。

5、固定头部的byte 2

是用来保存接下去的变长头部+消息体的总大小的。

但是不是并不是直接保存的,同样也是可以扩展的,其机制是,前7位用于保存长度,后一部用做标识。

我举个例了,即如果计算出后面的大小为0<length<=127的,正常保存

如果是127<length<16383的,则需要二个字节保存了,将第一个字节的最大的一位置1,表示未完。然后第二个字节继续存。

拿130来说,第一个字节存10000011,第二个字节存000000001,也就是0x83,0x01,把两个字节连起来看,第二个字节权重从2的8次开始。

同起可以加第3个字节,最多可以加至第4个字节。故MQTT协议最多可以实现268 435 455 (0xFF, 0xFF, 0xFF, 0x7F)将近256M的数据。可谓能伸能缩。

 可变头部

这个是可变头部的全貌。

1、Protocol Name

首先最上面的8个字节是Protocol Name(编码名),UTF编码的字符“MQIsdp”,头两个是编码名提长为6。

这里多说一些,接下去的协议多采用这种方式组合,即头两个字节表示下一部分的长,然后后面跟上内容。这里头两个字节长为6,下面跟6个字符“MQIsdp”。

2、Protocol Version

Protocol Version,协议版本号,v3 也是固定的。

3、Connect Flag

Connect Flag,连接标识,有点像固定头部的。8位分别代表不同的标志。第1个字节保留。

Clean Session,Will flag,Will Qos, Will Retain都是相对于CONNECT消息来说的。

Clean Session:
0表示如果订阅的客户机断线了,那么要保存其要推送的消息,如果其重新连接时,则将这些消息推送。
1表示消除,表示客户机是第一次连接,消息所以以前的连接信息。


Will Flag:
表示如果客户机在不是在发送DISCONNECT消息中断,比如IO错误等,将些置为1,要求重传。
并且下且的WillQos和WillRetain也要设置,消息体中的Topic和MessageID也要设置,就是表示发生了错误,要重传。

Will Qos:
在CONNECT非正常情况下设置,一般如果标识了WillFlag,那么这个位置也要标识。

Will RETAIN:同样在CONNECT中,如果标识了WillFlag,那么些位也一定要标识

usename flag和passwordflag:
用来标识是否在消息体中传递用户和密码,只有标识了,消息体中的用户名和密码才用效,只标记密码而不标记用户名是不合法的。

4、Keep Alive,表示响应时间,如果这个时间内,连接或发送操作未完成,则断开tcp连接,表示离线。

5、Connect Return Code即通常于CONNACK消息中,表示返回的连接情况,我可以通过此检验连接情况。

6、Topic Name,订阅消息标识,MQTT是基于订阅/发布的消息,那么这个就是消息订阅的标识,像新闻客户端里的订阅不同的栏目一样。用于区别消息的推送类别。

主要用于PUBLISH和SUBSCRIBE中。最大可支持32767个字符,即4个字节。

消息体(PayLoad)

只有3种消息有消息体CONNECT,SUBSCRIBE,SUBACK

CONNECT主要是客户机的ClientID,订阅的Topic和Message以及用户名和密码,其于变长头部中的will是对应的。

SUBSCRIBE是包含了一系列的要订阅的主题以及QOS。

SUBACK是用服务器对于SUBSCRIBE所申请的主题及QOS进行确认和回复。

PUBLISH是消息体中则保存推送的消息,以二进制形式,当然这里的编辑可自定义。

7、Message Identifier

包含于PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK.

其为16位字符表示,用于在Qos为1或2时标识Message的,保证Message传输的可靠性。

至于具体的消息例子,我们在后面的代码中慢慢体现。

MQTT协议详解,非常易懂_黑贝是条狗的博客-CSDN博客_mqtt协议详解

5.2  MQTT可变头

MQTT数据包中包含一个可变头,它驻位于固定的头和负载之间。可变头的内容因数据包类型而不同,较常的应用是作为包的标识:

很多类型数据包中都包括一个2字节的数据包标识字段,这些类型的包有:PUBLISH (QoS > 0)、PUBACK、PUBREC、PUBREL、PUBCOMP、SUBSCRIBE、SUBACK、UNSUBSCRIBE、UNSUBACK。

5.3  Payload消息体

Payload消息体位MQTT数据包的第三部分,包含CONNECT、SUBSCRIBE、SUBACK、UNSUBSCRIBE四种类型的消息:

(1)CONNECT,消息体内容主要是:客户端的ClientID、订阅的Topic、Message以及用户名和密码。

(2)SUBSCRIBE,消息体内容是一系列的要订阅的主题以及QoS。

(3)SUBACK,消息体内容是服务器对于SUBSCRIBE所申请的主题及QoS进行确认和回复。

(4)UNSUBSCRIBE,消息体内容是要订阅的主题。



链接:https://www.jianshu.com/p/5c42cb0ed1e9
 

https://blog.csdn.net/anxianfeng55555/article/details/80908795

MQTT协议讲解

https://www.zstel.com/support/327-cn.html

MQTT开发C代码

MQTT学习_酣楼驻海的博客-CSDN博客

MQTT 开发笔记(python)

MQTT 向别人介绍的简单教程

https://www.cnblogs.com/xiaoyehack/p/9916817.html

2019.05.30 安装新的mysqlclient

报错mysql_config: command not found

运django 报错:ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3.

pip install mysqlclient   安装最新

2019.05.30django

要在上面安装django,直接用命令 pip install django 安装

判断是否安装成功:

[root@Lrw888 ~]# python
>>> import djangoo
>>> django.get_version()
'2.2.1'
>>> 

返回2.2.1 表示安装成功2.2.1版本

2019.05.24

发现 操作数据库的程序 隔一段时间 没有插入数据成功,原理是mysql链接默认设置8小时没有数据插入就自动关闭链接。

demo 客户端确实经常8小时没有数据插入,所以设置数据库8小时断开改为 21天。

wait_timeout=31536000

interactive_timeout=31536000

2019.05.20安装anaconda (anaconda就是python+多个常用包的集合体)

C++/C 写MQTT客户端实在太啰嗦了,决定用python来写。

安装anaconda3,安装后python -v 依然显示2.6版,原来是还有配置路径:


 vim ~/.bashrc ,在文件最后加上 export  PATH="/root/anaconda3/bin:$PATH" 即可,注意,此处只是演示,具体路径需根据自己安装的位置进行更改。
第三步:安装好以后,输入命令,使环境变量生效 :source ~/.bachrc,然后重启终端

2019.05.15 下载下来的client 库是动态库.so,要编程静态库。

1、需要安装openssl和openssl-devel

安装openssl和openssl-devel_零点零一的博客-CSDN博客_openssl openssl-devel

网络安全:SSL工作原理 - phlsheji - 博客园

MQTT服务器

选择了轻量的Mosquitto

运行:mosquitto -c /etc/mosquitto/mosquitto.conf -d

Mosquitto简要教程(安装/使用/测试):[移动] Mosquitto简要教程(安装/使用/测试)_shagoo的博客-CSDN博客_mosquitto 教程

1‘MQTT的局限:

MQTT客户端C代码:https://www.jianshu.com/p/d309de966379

http://www.cnblogs.com/star91/p/4889820.html《菜鸟是如何打造智能家居系统的》

Centos7-mqtt消息中间件mosquitto的安装和配置 - FeMiner - 博客园

Paho -物联网 MQTT C Cient的实现和详解》

Paho -物联网 MQTT C Cient的实现和详解 - 阿进的写字台 - 博客园

客户端代码库:

https://www.eclipse.org/paho/downloads.php

《Paho MQTT C Client Library》

Paho MQTT C Client Library: MQTT Client library for C

测试工具

可视化工具:

MQTTBox ,MQTTBox有两种使用的方式:一种为Chrome插件;另外一种为Windows程序安装。

安装步骤

1)下载安装软件:读者可以根据自己的喜好,下载不同的版本:此处为Chrome版本的下载地址(需FQ);此处为Windows安装程序

2)根据安装向导的提示,完成MQTTBox的安装

3)打开安装好的应用图标,如下图所示

测试消息发布/订阅(Pub/Sub)功能

MQTT协议中通过主题(Topic)在消息发布者和

1)建立MQTT连接,如下图所示,点击“Create MQTT Client”

2)指定连接相关信息,包括连接名称(可以随意输入)、协议(选择mqtt/tcp)和主机地址(安装在本地,MQTT缺省端口为1883,所以输入127.0.0.1:1883),然后单击“Save”保存。连接中一些别的选项先保持缺省值,读者对MQTT协议比较熟悉之后,就可以了解这些选项的意义。

保存成功后进入如下的界面,接下来可以开始测试消息发布和订阅。如下图所示,绿色“Connected”按钮表明当前MQTT连接已经成功

3)首先我们开启一个订阅,如下图所示。“Topic to subscribe”里填入要订阅的主题“windows”;“QoS”字段选择“0 - Almost Once”;然后点击“Subscribe”按钮

4)设置好订阅的主题后,在发布这边输入如下的信息。“Topic to publish”中输入“windows”,这里输入的主题的名字必须和订阅那里的输入相同;“QoS”中选择“0 - Almost Once”;“Payload”中输入任何内容都可以,如下图所示输入了一组JSON字符串;所有内容输入完毕之后,点击“Publish”按钮

5)在订阅端就会收到由服务器端转发的消息内容,如下图所示。

6)打开EMQ的管理员控制台,可以看到一些相关的统计数据已经发生了变化。比如在“The messages data”表格中,“qos0/received”的值为1,说明EMQ收到了1条QoS0的消息;“qos0/sent”的值为1,表示EMQ转发了一条QoS0的消息。

好了,EMQ君带领着大家初步领略了MQTT服务器能够提供的基本功能,如果读者想了解其它MQTT服务器在不同平台上的安装的话,请参考以下系列文章。

Ubuntu上搭建EMQ MQTT服务器

Ubuntu上搭建EMQ Mosquito服务器

Ubuntu上搭建EMQ Apollo服务器

Windows上搭建Mosquitto MQTT服务器

Windows上搭建Apache Apollo MQTT服务器

小礼物走一走,来简书关注我



作者:EMQ
链接:https://www.jianshu.com/p/e5cf0c1fd55c
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

MQTT的简洁说明:

一、了解MQTT基本知识

1.在MQTT通讯过程中,有三种身份,分别是发布者(publisher)、代理(broker)、和订阅者(subscriber)。

2.MQTT传输的消息分为:主题(topic)和负载(payload)两部分:

  • Topic,为消息的类型,是由客户端发布时指定的,当另外一个客户端订阅(subscribe)主题后,就会收到该主题的消息内容(payload)。
  • payload当然就是内容了,它和主题一样都存在数据包(packet)中。

3.当应用数据通过MQTT网络发送时,MQTT会把与之相关的服务质量(QoS)和主题名(Topic)相关连。

QoS在MQTT中有(摘自MQ 遥测传输 (MQTT) V3.1 协议规范):

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

MQTT.js只是支持了MQTT协议,并没有支持QoS,也就是说,只支持最低级别的“至多一次”(QoS0)。

4.在MQTT客户端上干什么?

  • 发布其他客户端会订阅的信息
  • 订阅其它客户端发布的消息
  • 退订或删除应用程序的消息
  • 断开与服务器连接。

5.MQTT服务器又干什么?

  • 接受来自客户的网络连接
  • 向订阅的客户转发应用程序消息

6.MQTT协议数据包(packet)结构

在MQTT协议中,一个MQTT数据包由:固定头(Fixed header)、可变头(Variable header)、消息体(payload)三部分构成。
这里只了解消息体,固定头和可变头并不需要我们手动写。
payload消息体包含CONNECT、SUBSCRIBE、SUBACK、UNSUBSCRIBE四种类型的消息:

  • CONNECT,消息体内容主要是:客户端的ClientID、订阅的Topic、Message以及用户名和密码。
  • SUBSCRIBE,消息体内容是一系列的要订阅的主题以及QoS。
  • SUBACK,消息体内容是服务器对于SUBSCRIBE所申请的主题及QoS进行确认和回复。
  • UNSUBSCRIBE,消息体内容是要订阅的主题。

7.MQTT协议规定的方法(重要,无论在那个框架里这是通用的)

(1)Connect    与服务器建立连接。
(2)Disconnect    与服务器断开TCP/IP会话。
(3)Subscribe    订阅。
(4)UnSubscribe    取消订阅。
(5)Publish    发送消息请求,发送完成后返回应用程序线程。
二、实现(具体的API稍后呈现)

客户端1:(发布消息)
let mqtt = require('mqtt')
let client = mqtt.connect('mqtt://localhost:233')

client.on('connect', () => {
    setInterval(function() {
        let message = new Date().toLocaleString()
        //每隔1s发布主题为dialog的消息
        client.publish('dialog', message, {
            qos: 0,         //可以丢失
            retain: false   //不保留
        })
    }, 1000)
})

客户端2:(接收消息)
let mqtt = require('mqtt')
let client = mqtt.connect('mqtt://localhost:233')

client.on('connect', () => {
    //订阅主题为dialog的消息
    client.subscribe('dialog')
})
client.on('message', (topic, message) => {
    //打印主题
    console.log(topic)
    //打印消息,是buffer形式
    console.log(message.toString())
})

服务端:
const mosca = require('mosca');
let settings = {
    port: 233,
};
let server = new mosca.Server(settings);

server.on('ready', () => {
    console.log('server is running');
});
server.on('clientConnected', (client) => {
    console.log(client);
});
server.on('published', (packet, client) => {
    //服务器作为中转站,可以打印数据包中的内容
    console.log(packet.payload);
})

运行结果


三、具体API(时间不够,我先不写了)
先放几个链接日后我自行翻译:
mosca的http://www.mosca.io/docs/lib/server.js.html#Server
mqtt.js的https://www.npmjs.com/package/mqtt#api
mqtt中文协议:https://www.gitbook.com/book/mcxiaoke/mqtt-cn/details,没什么用啊用别人框架都不需要这个

作者:lhdoeo
链接:https://www.jianshu.com/p/b452e2cee0d6

posted on 2022-10-04 01:28  bdy  阅读(256)  评论(0编辑  收藏  举报

导航