• IOT 之 MQTT协议


    1、MQTT是啥

    MQTT 协议 是基于发布/订阅模式的物联网通信协议,凭借简单易实现、支持 QoS、报文小等特点,占据了物联网协议的半壁江山。

    Mqtt 协议是建立在TCP连接之上的应用层协议,是为了解决复杂网络环境下的通信的解决方案。

    官方网站:Getting started

    2、MQTT协议解析

    2.1 mqtt 角色

    mqtt 的主要核心在于发布订阅模式,所以常规的理解发布订阅存在三个角色

    publisher : 消息的发布者,一般是设备端

    subscriber :消息的订阅者,一般是设备端

    Broker : 消息的中专者,在这里也叫broker,实现MQTT协议的服务器程序。

    2.2 协议的格式

    MQTT 协议将协议本身占用的额外消耗最小化,消息头部最小只需要占用 2 个字节。

    MQTT 的消息格式分三部分:

    固定长度头部,2 个字节,所有消息类型里都有

    可变长度头部,只有某些消息类型里有

    Payload,只有某些消息类型里有

    2.3 消息类型

    MQTT 的主要消息类型下面这些,也就是说只有这么几条协议。

    • CONNECT / CONNACK
    • PUBLISH / PUBACK
    • SUBSCRIBE / SUBACK
    • UNSUBSCRIBE / UNSUBACK
    • PINGREQ / PINGRESP
    • DISCONNECT

    上面做了分组,基本上都是请求响应的模式。

    可以简单的记一下:

    rec -> record 记录,保存消息

    rel ->release 释放消息,也就是删除消息

    com ->complete 操作完成。

    2.4 Topic的定义

    订阅的单位是topic,但是这里面有一些规则类似restful ,也就是路径的匹配。

    这里主要有四种特殊的符号

    1.斜杠(“/” )用于分割主题的每个层级,为主题名提供一个分层结构

    2.多层通配符 ,井字符号(“#”)是用于匹配主题中任意层级的通配符。多层通配符表示它的父级和任意数量的子层级。只能放在尾部

    3.单层通配符,加号 (“+”) 是只能用于单个主题层级匹配的通配符。

    4.以 $ 开头的主题,客户端禁止使用,服务端实现可以将 $ 开头的主题名用作其他目的,也就是特殊用处

    举几个小例子

    sport/tennis/player1/# 可以匹配 sport/tennis/player1 ,sport/tennis/player1/ranking,也就是只要以topic开头的都可以

    sport/t+/player1 可以匹配 sport/a/player1 sport/b/player1 等等,+只能代表一组字符

    2.5三个QoS等级

    QoS实际是客户端和Broker之间的一个服务可靠等级。这个可靠等级最终计算也是取决于订阅和发布双方。

    MQTT 设计了 3 个 QoS 等级。

    • QoS 0:消息最多传递一次,如果当时客户端不可用,则会丢失该消息。
    • QoS 1:消息传递至少 1 次。可能存在发送多次相同的消息,直到rec
    • QoS 2:消息仅传送一次。有一个确认的操作,比较耗。

    下面看下QoS 2 下消息的发送方式:

    可以只看publisher和broker之间的消息往来。

    1.publisher发布消息,broker接受之后,回复publisher pubrec,publisher 就删除本地的消息

    2. publisher删除之后,通知broker 删除成功pubrel ,

    3.broker 发布完成之后也删除消息,并且回复publisherpubcom

    以下情况下可以选择 QoS 0

    • 可以接受消息偶尔丢失。
    • 在同一个子网内部的服务间的消息交互,或其他客户端与服务端网络非常稳定的场景。

    以下情况下可以选择 QoS 1

    • 对系统资源消耗较为关注,希望性能最优化。
    • 消息不能丢失,但能接受并处理重复的消息。

    以下情况下可以选择 QoS 2

    • 不能忍受消息丢失(消息的丢失会造成生命或财产的损失),且不希望收到重复的消息。
    • 数据完整性与及时性要求较高的银行、消防、航空等行业。

    2、MQTT和Http ,TCP有什么不同?

    Mqtt 和 http 都属于应用层协议,并且http应用更广泛。为什么iot还是选择了Mqtt协议,我理解的是mqtt 做了物联网的一些逻辑,但是http 没有,并且不利于推送

    Mqtt 和Tcp 协议在不同的层级,MQTT的底层实现依赖于TCP,你可以自己实现mqtt叫其他的协议名字也可以,但是现在mqtt已经是广泛接受的一种协议。

    3、MQTT client的例子

    这里选择了一个免费的broker,tcp://broker-cn.emqx.io,端口1883

    添加maven引用

    1. <dependency>
    2. <groupId>org.eclipse.pahogroupId>
    3. <artifactId>org.eclipse.paho.client.mqttv3artifactId>
    4. <version>1.2.5version>
    5. dependency>

    MqttSample.java

    1. import org.eclipse.paho.client.mqttv3.*;
    2. import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
    3. public class MqttSample {
    4. public static void main(String[] args) {
    5. String topic = "xiangcai/topic";
    6. String content = "Hello World";
    7. int qos = 2;
    8. String broker = "tcp://broker.emqx.io:1883";
    9. String clientId = MqttClient.generateClientId();
    10. // 持久化
    11. MemoryPersistence persistence = new MemoryPersistence();
    12. // MQTT 连接选项
    13. MqttConnectOptions connOpts = new MqttConnectOptions();
    14. try {
    15. MqttClient client = new MqttClient(broker, clientId, persistence);
    16. // 设置回调
    17. client.setCallback(new SampleCallback());
    18. // 建立连接
    19. System.out.println("Connecting to broker: " + broker);
    20. client.connect(connOpts);
    21. System.out.println("Connected to broker: " + broker);
    22. // 订阅 topic
    23. client.subscribe(topic, qos);
    24. System.out.println("Subscribed to topic: " + topic);
    25. // 发布消息
    26. MqttMessage message = new MqttMessage(content.getBytes());
    27. message.setQos(qos);
    28. client.publish(topic, message);
    29. System.out.println("Message published");
    30. client.disconnect();
    31. System.out.println("Disconnected");
    32. client.close();
    33. System.exit(0);
    34. } catch (MqttException me) {
    35. System.out.println("reason " + me.getReasonCode());
    36. System.out.println("msg " + me.getMessage());
    37. System.out.println("loc " + me.getLocalizedMessage());
    38. System.out.println("cause " + me.getCause());
    39. System.out.println("excep " + me);
    40. me.printStackTrace();
    41. }
    42. }
    43. }

    回调代码SampleCallback.java

    1. import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
    2. import org.eclipse.paho.client.mqttv3.MqttCallback;
    3. import org.eclipse.paho.client.mqttv3.MqttMessage;
    4. public class SampleCallback implements MqttCallback {
    5. // 连接丢失
    6. public void connectionLost(Throwable cause) {
    7. System.out.println("connection lost:" + cause.getMessage());
    8. }
    9. // 收到消息
    10. public void messageArrived(String topic, MqttMessage message) {
    11. System.out.println("Received message: \n topic:" + topic + "\n Qos:" + message.getQos() + "\n payload:" + new String(message.getPayload()));
    12. }
    13. // 消息传递成功
    14. public void deliveryComplete(IMqttDeliveryToken token) {
    15. System.out.println("deliveryComplete");
    16. }
    17. }

    其他语言的连接实例

    建立 MQTT 客户端连接 | EMQX Cloud 文档

    4、mqtt的实现和工具

    mqtt broker的实现

    到目前为止,比较流行的开源 MQTT 服务器有几个:

    • Eclipse Mosquitt

    使用 C 语言实现的 MQTT 服务器。Eclipse 组织还还包含了大量的 MQTT 客户端项目:Eclipse Paho | The Eclipse Foundation

    • EMQX

    使用 Erlang 语言开发的 MQTT 服务器,内置强大的规则引擎,支持许多其他 IoT 协议比如 MQTT-SN、 CoAP、LwM2M 等。

    • 还有一些mq 也实现了mqtt协议

    5.mqtt 客户端模拟工具

    客户端模拟工具可以理解为postman,就是为了测试,客户端工具比较多,当前使用的是

    mqttx,可以看下界面,看起来还是比较清爽的,消息收发类似聊天的方式

    总结

    在刚开始看的时候对这个协议还是感觉很神秘的,等到现在回头看可以理解为一个通用的服务器,

    只不过定义好了消息通信的格式,我们要做的只是理解,知道这个服务器是怎么回事,知道怎么通信就可以了

  • 相关阅读:
    淘宝问问:电商AI,重新定义购物体验
    Unity项目迁移
    共享内存区
    k8s-helloword部署一个应用
    汇编-间接寻址(处理数组)
    【Go ~ 0到1 】 第二天 6月25 Switch语句,数组的声明与遍历
    8、多进程之间的通信
    外包干了4年,技术退步明显.......
    【日常业务开发】Java实现异步编程
    iPhone开发--字节数组NSMutableData删除
  • 原文地址:https://blog.csdn.net/perfect2011/article/details/121081436