MQTT
MQTT使用的底层传输协议基础设施。
- 客户端使用它连接服务端。
- 它提供有序的、可靠的、双向字节流传输。
客户端 Client
使用MQTT的程序或设备。客户端总是通过网络连接到服务端。它可以
- 发布应用消息给其它相关的客户端。
- 订阅以请求接受相关的应用消息。
- 取消订阅以移除接受应用消息的请求。
- 从服务端断开连接。
服务端 Server
一个程序或设备,作为发送消息的客户端和请求订阅的客户端之间的中介。服务端
- 接受来自客户端的网络连接。
- 接受客户端发布的应用消息。
- 处理客户端的订阅和取消订阅请求。
- 转发应用消息给符合条件的已订阅客户端。
订阅 Subscription
订阅包含一个主题过滤器(Topic Filter)和一个最大的服务质量(QoS)等级。订阅与单个会话(Session)关联。会话可以包含多于一个的订阅。会话的每个订阅都有一个不同的主题过滤器。
主题名 Topic Name
附加在应用消息上的一个标签,服务端已知且与订阅匹配。服务端发送应用消息的一个副本给每一个匹配的客户端订阅。
主题过滤器 Topic Filter
订阅中包含的一个表达式,用于表示相关的一个或多个主题。主题过滤器可以使用通配符。
会话 Session
客户端和服务端之间的状态交互。一些会话持续时长与网络连接一样,另一些可以在客户端和服务端的多个连续网络连接间扩展。
控制报文 MQTT Control Packet
通过网络连接发送的信息数据包。MQTT规范定义了十四种不同类型的控制报文,其中一个(PUBLISH报文)用于传输应用消息。
状态存储 Storing state
为了提供服务质量保证,客户端和服务端有必要存储会话状态。在整个会话期间,客户端和服务端都必须存储会话状态 [MQTT-4.1.0-1]。会话必须至少持续和它的活跃网络连接同样长的时间 [MQTT-4.1.0-2]。
服务端的保留消息不是会话状态的组成部分。服务端应该保留那种消息直到客户端删除它。
网络连接 Network Connections
MQTT协议要求基础传输层能够提供有序的、可靠的、双向传输(从客户端到服务端 和从服务端到客户端)的字节流。
无连接的网络传输协议如UDP是不支持的,因为他们可能会丢失数据包或对数据包重排序。
服务质量等级和协议流程 QoS
MQTT按照这里定义的服务质量 (QoS) 等级分发应用消息。分发协议是对称的,在下面的描述中,客户端和服务端既可以是发送者也可以是接收者。分发协议关注的是从单个发送者到单个接收者的应用消息。服务端分发应用消息给多个客户端时,每个客户端独立处理。分发给客户端的出站应用消息和入站应用消息的QoS等级可能是不同的。
QoS 0:最多分发一次
消息的分发依赖于底层网络的能力。接收者不会发送响应,发送者也不会重试。消息可能送达一次也可能根本没送达。
对于QoS 0的分发协议,发送者
- 必须发送QoS等于0,DUP等于0的PUBLISH报文 [MQTT-4.3.1-1]。
对于QoS 0的分发协议,接收者
- 接受PUBLISH报文时同时接受消息的所有权。
QoS 1: 至少分发一次
服务质量确保消息至少送达一次。QoS 1的PUBLISH报文的可变报头中包含一个报文标识符,需要PUBACK报文确认。2.3.1节提供了有关报文标识符的更多信息。
对于QoS 1的分发协议,发送者
-
每次发送新的应用消息都必须分配一个未使用的报文标识符。
-
发送的PUBLISH报文必须包含报文标识符且QoS等于1,DUP等于0。
-
必须将这个PUBLISH报文看作是 未确认的 ,直到从接收者那收到对应的PUBACK报文。
对于QoS 1的分发协议,接收者
-
响应的PUBACK报文必须包含一个报文标识符,这个标识符来自接收到的、已经接受所有权的PUBLISH报文。
-
发送了PUBACK报文之后,接收者必须将任何包含相同报文标识符的入站PUBLISH报文当作一个新的消息,并忽略它的DUP标志的值。
QoS 2: 仅分发一次
这是最高等级的服务质量,消息丢失和重复都是不可接受的。使用这个服务质量等级会有额外的开销。
QoS 2的消息可变报头中有报文标识符。2.3.1节提供了有关报文标识符的更多信息。QoS 2的PUBLISH报文的接收者使用一个两步确认过程来确认收到。
对于QoS 2的分发协议,发送者
-
必须给要发送的新应用消息分配一个未使用的报文标识符。
-
发送的PUBLISH报文必须包含报文标识符且报文的QoS等于2,,DUP等于0。
-
必须将这个PUBLISH报文看作是 未确认的 ,直到从接收者那收到对应的PUBREC报文。4.4节有一个关于未确认消息的讨论。
-
收到PUBREC报文后必须发送一个PUBREL报文。PUBREL报文必须包含与原始PUBLISH报文相同的报文标识符。
-
必须将这个PUBREL报文看作是 未确认的 ,直到从接收者那收到对应的PUBCOMP报文。
-
一旦发送了对应的PUBREL报文就不能重发这个PUBLISH报文。
对于QoS 2的分发协议,接收者
-
响应的PUBREC报文必须包含报文标识符,这个标识符来自接收到的、已经接受所有权的PUBLISH报文。
-
在收到对应的PUBREL报文之前,接收者必须发送PUBREC报文确认任何后续的具有相同标识符的PUBLISH报文。 在这种情况下,它不能重复分发消息给任何后续的接收者。
-
响应PUBREL报文的PUBCOMP报文必须包含与PUBREL报文相同的标识符。
-
发送PUBCOMP报文之后,接收者必须将包含相同报文标识符的任何后续PUBLISH报文当作一个新的发布。
消息分发重试 Message delivery retry
客户端设置清理会话(CleanSession)标志为0重连时,客户端和服务端必须使用原始的报文标识符重发任何未确认的PUBLISH报文(如果QoS>0)和PUBREL报文 [MQTT-4.4.0-1]。这是唯一要求客户端或服务端重发消息的情况。
消息收到 Message receipt
服务端接管入站应用消息的所有权时,它必须将消息添加到订阅匹配的客户端的会话状态中。匹配规则定义见 4.7节 [MQTT-4.5.0-1]。
正常情况下,客户端收到发送给它的订阅的消息。客户端也可能收到不是与它的订阅精确匹配的消息。如果服务端自动给客户端分配了一个订阅,可能发生这种情况。正在处理UBSUBSCRIBE请求时也可能收到消息。客户端必须按照可用的服务质量(QoS)规则确认它收到的任何PUBLISH报文,不管它选择是否处理报文包含的应用消息 [MQTT-4.5.0-2]。
消息排序 Message ordering
实现本章定义的协议流程时,客户端必须遵循下列规则:
-
重发任何之前的PUBLISH报文时,必须按原始PUBLISH报文的发送顺序重发(适用于QoS 1和QoS 2消息)[MQTT-4.6.0-1]。
-
必须按照对应的PUBLISH报文的顺序发送PUBACK报文(QoS 1消息)[MQTT-4.6.0-2]。
-
必须按照对应的PUBLISH报文的顺序发送PUBREC报文(QoS 2消息)[MQTT-4.6.0-3]。
-
必须按照对应的PUBREC报文的顺序发送PUBREL报文(QoS 2消息)[MQTT-4.6.0-4]。
服务端必须默认认为每个主题都是有序的。它可以提供一个管理功能或其它机制,以允许将一个或多个主题当作是无序的 [MQTT-4.6.0-5]。
服务端处理发送给有序主题的消息时,必须按照上面的规则将消息分发给每个订阅者。此外,它必须按照从客户端收到的顺序发送PUBLISH报文给消费者(对相同的主题和QoS)[MQTT-4.6.0-6]。