mqtt服务器搭建实验报告
1. 如何采用mqtt协议实现android消息推送
使用一个代理服务器message broker,客户端client连接上这个服务器,然后告诉服务器,可以接收哪些类型的消息,同时client也可以发布自己的消息,这些消息根据协议的内容,可以别的client获取。这样就实现了消息推送。消息推送是通过一定的技术标准或协议,在互联网上通过定期传送用户需要的信息来减少信息过载的一项新技术。
如果想要使用消息推送,推荐使用深圳极光的消息推送系统。深圳极光是国内首个为移动应用开发者提供专业、高效的消息推送服务的产品。品牌成长的过程,就是与客户肩并肩迈向成功的过程。极光将以市场为导向,以创新为动力,以技术为支持,不断用心努力,为每一位尊贵的客户提供极致的服务。
2. 黑群晖怎样搭建MQTT服务器
1、打开群晖Docker,注册表搜索:mqtt;
2、点击下载好的镜像文件创建容器,输入容器名字,点击高级设置
3、勾选启用自动重新启动
4、点击网络—-勾选与docker host相同的网络,点击应用,一直下一步直到创建完成
3. 在云服务器上搭建了mqtt,为什么手机连接不上mqtt,要怎么做才能连接上求求大神帮忙
MQTT协议是广泛应用的物联网协议,使用测试MQTT协议需要MQTT的代理。有两种方法使用MQTT服务,一是租用现成的MQTT服务器,如阿里云,网络云,华为云等公用的云平台提供的MQTT服务,使用公用的MQTT服务器的好处是省事,但如果仅仅用于测试学习还需要注册帐号,灵活性差些,有的平台还需要付费。另一方法是自己使用开源的MQTT组件来搭建。
MQTT服务器非常多,如apache的ActiveMQ,emtqqd,HiveMQ,Emitter,Mosquitto,Moquette等等。
这里介绍的是用轻量级的mosquitto开源项目来搭建一个属于自己的MQTT服务器。
第一步:需要安装一台linux主机,这不多介绍,可以使用真机安装也可以使用虚拟机安装。如果仅仅是自己测试使用都可以。
第二步:下载mosquitto需要的依赖
sudo apt-get install libssl-devsudo apt-get install uuid-devsudo apt-get install cmake
第三步:下载mosquitto并解压,现在mosquitto官网最新的版本是1.5.1
tar xzvf mosquitto-1.5.1.tar.gz
第四步:编译
cd mosquitto-1.5.1/
make
make install
第五步:启动mosquitto
./mosquitto -v
1535473957: mosquitto version 1.5.1 starting
1535473957: Using default config.
1535473957: Opening ipv4 listen socket on port 1883.
1535473957: Opening ipv6 listen socket on port 1883.
这时候mosquitto就会以默认的参数启动。如果需要带配置文件可以修改配置文件mosquitto.conf,
启动时候加上参数 -c,
./mosquitto -c mosquitto.conf
可以看到,mosquitto监听的端口为1883.
这时候我们的MQTT服务器就搭建好了。可找一个mqtt客户端来测试一下。
先发布一个主题“home/garden/fountain/2”
内容是“hello world”
这时候在mosquitto会打印出下面的log
535474247: New connection from 192.168.1.105 on port 1883.
1535474247: New client connected from 192.168.1.105 as MQTT_FX_Client (c1, k60).
1535474247: No will message specified.
1535474247: Sending CONNACK to MQTT_FX_Client (0, 0)
1535474307: Received PINGREQ from MQTT_FX_Client
1535474307: Sending PINGRESP to MQTT_FX_Client
1535474339: Received PUBLISH from MQTT_FX_Client (d0, q0, r0, m0, 'home/garden/fountain/2', ... (12 bytes))
1535474367: Received PINGREQ from MQTT_FX_Client
1535474367: Sending PINGRESP to MQTT_FX_Client
订阅主题“home/garden/fountain/2”
可以看到收到了自己发布的消息。
用wireshark抓包
可以看到抓到了一个MQTT的publish的报文。
4. Android 中使用MQTT(第一篇)
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议。它是一种发布/订阅,极其简单和轻量级的消息传递协议,专为受限设备和低带宽,高延迟或不可靠的网络而设计。它的设计思想是轻巧、开放、简单、规范,易于实现。这些特点使得它对很多场景来说都是很好的选择,特别是对于受限的环境如机器与机器的通信(M2M)以及物联网环境。相对于XMPP,MQTT更加轻量级,并且占用的宽带低。
MQTT协议有以下特点:
那么问题来了?重连连接成功后重复接收到最后一条消息
MQTT推送消息订阅端重复接收问题。
(背景)订阅端断开的时候,发布端多次推送消息。
(现象)订阅端启动时,接收到最后一条推送消息有两次;即使Qos设置为2;依然是两次。
经排查是因为
MqttMessage的Retained设置为了true;
该值很多文章上只说了是 消息保留机制,若设置为true,mqtt服务器会保留每次发布的消息;较少提到 若订阅某主题的客户端重启,则会把此主题之前发布的消息重新推送到客户端。该值默认为false;去掉修改该值即可
那么问题来了?重连连接后手动那么多遗漏的消息,怎么选择只接收最新的一条消息呢?
MQTT推送消息订阅端重复接收问题。
(背景)订阅端断开的时候,发布端多次推送消息。
(现象)订阅端启动时,接收到msg1,msg2,msg3 (这三个消息都是同一个类型消息,只需要处理最新的msg3就好,不然界面会刷新三次)这个谁有什么好办法没呢?
GitHub地址: https://github.com/eclipse/paho.mqtt.android
mqtt的官方文档: http://mqtt.org/documentation
Github上有中文翻译: https://github.com/mcxiaoke/mqtt
在mole的build.gradle文件中添加依赖
在 AndroidManifest.xml 添加限权
在 AndroidManifest.xml 注册Service (MyMqttService为自己写的服务,下文会讲到)
5. 如何用mosquitto搭建服务器
Mosquitto是一款实现了消息推送协议MQTT v3.1的开源消息代理软件,提供轻量级的,支持可发布/可订阅的的消息推送模式,使设备对设备之间的短消息通信变得简单,比如现在应用广泛的低功耗传感器,手机、嵌入式计算机、微型控制器等移动设备。
Mosquitto官网:
MQTT协议:
客户端连接日志
1403334375: New connection from 121.201.8.163 on port 1883.
1403334375: New client connected from 121.201.8.163 as zhoujing (c0, k60, ujoyo).
1403334375: Sending CONNACK to zhoujing (0)
以上是一个客户端正常连接的日志。
第一行:服务器收到一个新的连接请求
1403334375: 表示连接的时间点
121.201.8.163: 客户端的IP地址
1883: 连接的服务器端口号
第二行:服务器为客户端建立连接
zhoujing (c0, k60, ujoyo): 客户端连接指定的ClientID为'zhoujing'
c0: 表示cleanSession=false,不清除session
k60: 表示keep-alive=60s
ujoyo: 表示使用的服务器账号为joyo
第三行:发送连接ACK包给客户端
客户端订阅过程日志
1403334375: Received SUBSCRIBE from zhoujing
1403334375: jiji/chat/9 (QoS 2)
1403334375: zhoujing 2 jiji/chat/9
1403334375: Sending SUBACK to zhoujing
第一行:服务器收到一个来自ClientID为zhoujing的订阅请求
第二行:服务器识别zhoujing订阅的主题为 jiji/chat/9,指定的QOS=2(有且只发送一次)
第三行:给ClientID=zhoujing客户端发送订阅ACK回包
服务器发送内容给客户端日志
1403334378: Sending PUBLISH to zhoujing (d0, q2, r0, m1, 'jiji/chat/9', ... (396 bytes))
1403334378: Received PUBREC from zhoujing (Mid: 1)
1403334378: Sending PUBREL to zhoujing (Mid: 1)
1403334378: Received PUBCOMP from zhoujing (Mid: 1)
第一行:服务器正在发送一个消息给ClientID=zhoujing的客户端,消息体大小为396 bytes,消息主题为‘jiji/chat/9’
(d0, q2, r0, m1)的解释, 以下参数具体含义,参考MQTT协议
d: 表示mqtt报头的DUP字段
q: 表示的QOS字段
r: 表示的是RETAIN
m: 表示的是消息ID,即mid
第二行:发布收稿阶段,有保证的交付第一部分
第三行:出版发行阶段,有保证的交付第二部分
第四行:发布完成,有保证的交付第三部分,至此一个内容发部过程完成
客户端主动断开连接的日志
客户端主动断开连接的只有一行日志,很简单。如下所示:
1403334380: Received DISCONNECT from JY_API_PUSH_CLIENT
接收客户端发布内容的过程日志
1403334389: Received PUBLISH from JY_API_PUSH_CLIENT (d0, q2, r0, m1, 'jiji/chat/9', ... (396 bytes))
1403334389: Sending PUBREC to JY_API_PUSH_CLIENT (Mid: 1)
1403334389: Received PUBREL from JY_API_PUSH_CLIENT (Mid: 1)
1403334389: Sending PUBCOMP to JY_API_PUSH_CLIENT (Mid: 1)
第一行:接收来自ClientID=JY_API_PUSH_CLIENT的发布请求,发布的消息主题为'jiji/chat/9',消息大小为396 bytes
第二行:服务器发送PUBREC给客户端,此过程与发送消息给客户端正好对称,只不过是Received和Sending的对象反过来而已
第三行:服务器接收到客户端已经释放的命令,内容交付第二步完成
第四行:通知客户端,接收完成,至此一个消息发布完成,内容交付第三步完成
同一个ClientID重复连接时
1403334510: New connection from 121.201.7.150 on port 1883.
1403334510: Client JY_API_PUSH_CLIENT already connected, closing old connection.
接收客户端心跳包
1403336716: Received PINGREQ from 36383A64663A6464003V0
1403336716: Sending PINGRESP to 36383A64663A6464003V0
客户端连接超时,服务器主动清除连接信息
1403336671: Client 33303A33393A3236003V0 has exceeded timeout, disconnecting.
客户端socket异常时的日志
1403337602: Socket error on client 351BBJKFX62C1, disconnecting.
1403337602: Socket error on client 351BBJKFX62C0, disconnecting.
6. 使用 Node-RED 处理 MQTT 数据
本文将介绍使用 Node-RED 连接到 MQTT 服务器,并对 MQTT 数据进行过滤和处理后再将其发送至 MQTT 服务器的完整操作流程。读者可以快速了解如何使用 Node-RED 对 MQTT 数据进行简单的流处理。
Node-RED 无论是在你本地的电脑上,还是树莓派等设备,亦或是云端服务器,都可以快速安装和使用,下面将使用两种比较常见的安装方式:
使用 npm 进行全局安装:
使用 Docker 进行安装:
如果使用的是 npm 进行的全局安装,那么在提示安装成功后,只需要在全局运行 node-red 命令就可以立即启动 Node-RED。
无论是使用 Docker 还是 npm 在启动成功后,我们只需要打开浏览器,输入当前地址加 1880 端口号,即可打开 Node-RED 的浏览器编辑器页面,例如在本地运行的话,打开浏览器,输入 http://127.0.0.1:1880,当看到如下图所示页面后,说明 Node-RED 已经成功启动:
本文将使用 EMQ 提供的 免费公共 MQTT 服务器,该服务基于 MQTT 物联网云平台 - EMQX Cloud 创建,服务器接入信息如下:
在下面的功能演示中,我们将提供一个使用 Node-RED 来处理接收到的包含温湿度信息的 JSON 数据,然后对温度值进行规则判断,当温度发生改变的时候,就将当前发生改变的温度值通过 MQTT 再次发送出去的简单使用案例。
我们首先在左侧菜单栏中,拖拽一个 MQTT in 的节点到页面中,双击节点后,右侧出现一个编辑 MQTT 节点的配置页面,我们根据内容提示,新建一个连接信息后,再填入 MQTT 的其它连接信息后,点击 Done 按钮后,即可保存该节点信息。
接入数据:我们拖拽一个 JSON 节点到页面中,可以在 JSON 节点的配置页面中,配置一个 Action,我们设置为 Always convert to JavasScript Object ,因为我们无法确定发送过来的数据是一个 JSON 格式的数据还是一个 JSON 字符串,因此第一步都将接收到的消息进行一个 JSON 转换。配置完成后,我们将该节点与 MQTT in 节点进行连接。
过滤数据
我们配置完成格式化发送过来的消息数据后,我们就可以拖拽一个 filter 节点到页面中,同样双击节点后,在配置页面中配置规则,我们先选择一个 Mode,我们设置为 blcok unless value changes ,过滤规则为需要当前接收到数据的值发生改变,因为目前数据为 JSON 格式,我们判断的是 JSON 数据内的某一个值,因此我们需要在 Property 这里设置值为 msg.payload.temperature 配置完成后我们点击 Done 按钮来保存数据过滤节点的配置,最后将该节点连接到上一步配置完成后的 JSON 节点。
使用模版
当过滤完数据后,同样拖拽一个 template 节点到页面中,双击节点后来配置模版内容,使过滤完成后的数据,能通过模版将数据进行输出。当然也可以不需要这个步骤,直接将过滤后的数据进行输出。
完成以上对数据的处理和过滤后,最后我们再来将处理完成后的数据使用 MQTT 将其发送出去,拖拽一个 MQTT out 的节点到页面中,填入和 MQTT in 节点相同的连接信息,配置一个用户接收数据的 Topic,最后保存完成后,再将其和 template 节点进行连接,点击右上角的 Deploy 按钮,即可对当前规则应用进行在线部署。
在完成整个流数据处理的功能编排以后,我们使用 MQTT 5.0 客户端工具 - MQTT X 来测试和验证该功能的可用性。我们新建一个连接,连接到刚才在 Node-RED 中配置的 MQTT 云服务地址,然后输入 MQTT in 节点内的 Topic 来发送一条消息,使 Node-RED 能够接收到我们发送的 MQTT 数据。
然后我们再在 MQTT X 中订阅一个在 MQTT out 节点内配置的 Topic,用于接收处理过的消息数据。当发送一条包含了温湿度的消息数据后,我们可以接收到一条根据我们设定的消息模版发送过来的消息,再次发送就无法接收到。
因为此时温度值没有发生变化,当我们再次修改温度值后,就会发现我们又接收到了一条包含提醒温度值发生变化的消息。
至此,我们完成了安装并使用 Node-RED 连接到 MQTT 云服务,以及对 MQTT 消息数据进行过滤和处理,最后再将处理完成后的数据消息发送至 MQTT 服务器的全部流程。
Node-RED 的交互和使用方式,即用 UI 方式描述通用业务逻辑,可以降低非专业开发人员的上手门槛,使用一个可视化工具快速地创建需要的复杂执行任务,可以通过简单 Node 即节点连接构建出复杂的任务,特别是针对一些物联网的应用场景,都很有帮助。
7. Android MQTT 通信
MQTT 协议 是基于发布/订阅模式的物联网通信协议,凭借简单易实现、支持 QoS、报文小等特点,占据了物联网协议的半壁江山。
常用于 IOT 物联网和一些需要服务端主动通知客户端的场景。
1. 导入依赖
2. 创建 MqttHelper 辅助类,设置回调监听
3. 连接 MQTT
连接成功或失败,以及中途的连接掉线,会触发 OnMqttStatusChangeListener 回调
4. MQTT 连接状态监听
5. MQTT 收发消息监听
onSubMessage 订阅的消息回调,因为存在订阅多个 topic 的情况,所以回调能知道是来自哪个 Topic 的消息;
onPubMessage 发布的消息回调,用于确认发布的消息是否发送成功。
6. MQTT 订阅 Topic
需要在 MQTT 连接成功后才能订阅 topic,否则订阅 Topic 不成功,收不到对应消息
7. MQTT 取消订阅 Topic
8. MQTT 发布消息
9. MQTT 断开连接
10. 通知设置
由于 MQTT 启动了一个 Service,而 Android 8.0 以上对于后台 Service 限制时长 5 秒;所以将 MqttService 绑定到 Notification 上成为了一个前台通知;通知的标题和内容显示可以在 strings.xml 中设置,对应属性如下:
Android 8.0 及以上开启前台服务绑定到通知,8.0 以下默认不启用,可将 mqtt_foreground_notification_low_26 设为 true,将 8.0 以下设备也开启前台通知服务
创建 MQTT 实例时需要传送参数 MqttOptions,下面将介绍下部分参数;
1. Topic
MQTT 是一种发布/订阅的消息协议, 通过设定的主题 Topic,
发布者向 Topic 发送的 payload 负载消息会经过服务器, 转发到所有订阅袜桥
该 Topic 的订阅者
通配符 : 假想移动端消息推送场景,有的系统消息是全体用户接收,有的消息是 Android 或 iOS 设备接收, 又或者是某些消息具体推送到用户,当然, 对应的多种类型消息可以通过多订阅几个对应的 Topic 解决,也可以使用通配符;
通配符有两个, " + " 和 " # ", 与正斜杠 " / " 组合使用;加号只能表示一级Topic, 井号可以表示任意层级 Topic; 例如: 订阅 Topic为 " System/+ ", 发布者发布的 Topic 可以是 System、System/Android、System/iOS; 但是不能是 System/iOS/123, 而订阅的 Topic 如果是" System/# " 则可以收到;
注意,只有订阅的 Topic 才可以使用 通配符, 发布和遗嘱的 Topic 不能包含通配符.
2. ClientID
发布者和订阅者都是属于客户端, 客户端与服务端建立连接之后,发送的第一个报文消息必须是 Connect 消息隐好缺,而 Connect 的消息载荷中必须包含 clientID 客户端唯一标识;
如果两个客户端的 clientID 一样, 则服务端记录第一个客户端连接之后再收到第二个客户端连接请求,则会向一个客户端发送 Disconnect 报文断开连接, 并连接第二个客户端, 而如果此时设置了自动重连, 第一个客户端再次连接,服务端又断开与第二个的连接, 连上第一个客户端, 如此将导灶辩致两个客户端不断的被挤掉重连.
注意: clientID 使用的字符最好是 大小写字母和数字, 长度最好限制在[1, 23] 之间;
3. 遗嘱消息
可选参数, 客户端没有主动向服务端发起 disconnect 断开连接消息,然而服务端检测到和客户端之间的连接已断开, 此时服务端将该客户端设置的遗嘱消息发送出去
应用场景: 客户端因网络等情况掉线之后, 可以及时通知到所有订阅该遗嘱 Topic 的客户端;
遗嘱 Topic 中不能存在通配符.
4. Session
客户端和服务端之间建立的会话状态, 一般用于消息保存, 如果设置清除 Session,则每次客户端和服务端建立连接会创建一个新的会话,之前连接中的消息不能恢复,
而设置不清除会话, 对应发布者发送的 qos 为 1和2 的消息,还未被订阅者接收确认,则需要保存在会话中, 以便订阅者下次连接可以恢复这些消息;
注意: Session 存储的消息是保存在内容中的, 所以如果不是重要的消息,最好是设置清除 Session, 或者设置 qos = 0;
5. 心跳包
标识客户端传输一次控制报文到下一次传输之间允许的空闲时间;在这段时间内,如果客户端没有其他任何报文发送,必须发送一个 PINGREQ 报文到服务器,而如果服务端在 1.5 倍心跳时间内没有收到客户端消息,则会主动断开客户端的连接,发送其遗嘱消息给所有订阅者。而服务端收到 PINGREQ 报文之后,立即返回 PINGRESP 报文给客户端
心跳时间单位为秒,占用2个字节,最大 2^16 - 1 = 65535秒(18小时12分钟15秒),设置为 0 表示不使用心跳机制; 心跳时间一般设置为几分钟或几十秒即可,时间短点可以更快的发出遗嘱消息通知掉线,但是时间短会增加消息频率,影响服务端并发; 微信长连接为 300 秒,而三大运营商貌似也有个连接时间最小的为 5 分钟。
6. qos
服务质量等级 qos 对应两部分,一是客户端到服务端发送的消息, 一是服务端到客户端订阅的消息; 从发布者到订阅者实际 qos 为两段路中 qos 最小的。
qos 可选值 0(最多交付一次)、1(最少交付一次)、2(正好交付一次);
qos = 0 :接收方不发送响应,发送方不进行重试;发送方只管发一次,不管是否发成功,也不管接收方是否成功接收,适用于不重要的数据传输;
qos = 1 :确保消息至少有一次到达接收方,发送方向接收方发送消息,需要等待接收方返回应答消息,如果发送方在一定时间之内没有收到应答,发送方继续下一次消息发送,直到收到应答消息,删除本地消息缓存,不再发送;所以接收方可能收到1-n次消息;适用于需要收到所有消息,客户端可以处理重复消息。
qos = 2 :确保消息只一次到达接收方,发送方和接收方之间消息处理流程最复杂;
Mqtt Qos 深度解读 和 MQTT协议QoS2 准确一次送达的实现
7. payload 负载消息
字节流类型, 是 MQTT 通信传输的真实数据
8. 保留消息
发布消息时设置, 对应参数 retain, 服务端将保留对应 Topic 最新的一条消息记录; 保留消息的作用是每次客户端连接上线都会收到其 Topic 的最后一条保留消息, 所以可能存在网络不稳定,频繁掉线重连,每次重连重复收到保留消息;
可以向对应的 Topic 发送一条 空消息,用于清除保留消息。
MQTT 服务搭建 Apache Apollo 服务器 搭建 MQTT 服务
Github 仓库
mqtt 协议
8. 如何通过php实现mqtt协议
MQTT是一个轻量级的消息发布/订阅协议,它是实现基于手机客户端的消息推送服务器的理想解决方案。
我们可以从这里下载该项目的实例代码,并且可以找到一个采用PHP书写的服务器端实现。
架构如下所示: