目录
相同点:
- MQTT 和 WebSocket 都是应用层协议
- 目前底层都是使用 TCP 协议确保可靠传输数据
- 都规定了自己的报文(消息)结构
- 都支持双向通信
- 都使用二进制编码(有别于 HTTP 这一类基于文本编码的协议)
- 都是公开标准 mqttrfc6455
不同点:
通信模型不同
WebSocket 是一种简单的报文协议,着重解决浏览器和服务端不能进行双向通信的问题。本质上有点像是 TCP 协议之上的 UDP 协议。WebSocket 仅仅定义了会话的发起方式和报文格式及类型。如何使用报文通信全由应用程序(各浏览器)控制。
MQTT 则是一种比较复杂的消息协议。MQTT 不仅规定了具体的协议编码,还规定了客户端和服务器的通信模型。具体来说就是MQTT是一种面向主题(topic)的消息广播协议。客户端可以创建、加入和订阅任意主题,并向主题发布消息或者接收广播消息。除此之外,MQTT 还规定了消息的投放级别(QoS),支持至少一次、至多一次和精确投递三种级别,在协议层规定了是否会产生重复投递。
总结下来,MQTT 是一套比较复杂的消息投递协议,而 WebSocket则只是在TCP协议之上实现了简单的报文通信。两种协议工作层次不一样。从这个意义上讲,MQTT 可以工作在 WebSocket之上。
报文结构不同
虽然两都均使用二进行编码,但 WebSocket 的报文要远比 MQTT 简单。
WebSocket 报文结构如下:
WebSocket 报文结构
最核心的就是我标出来的 opcode 域,只有 4 位,最多有 16 种组合:
- 0 表示当前消息是上一条消息一部分
- 1 表示当前消息传输的是文本内容
- 2 表示当前消息传输的是二进制内容
- 3-7 预留
- 8 表示关闭会话
- 9 ping
- 10 pong
- 11-15 预留
虽然 WebSocket 规定了 ping 和 pong 报文,却并强制要求大家实现,完全看应用代码怎么写。
MQTT 协议的报文就非常复杂了,整体上分三部分:
Fixed Header, present in all MQTT Control Packets |
Variable Header, present in some MQTT Control Packets |
Payload, present in some MQTT Control Packets |
每个报文都有固定的头部信息。根据类型的不同,有些报文还有额外的头部信息。然后有消息内容本身。
MQTT 报文头部结构
大家注意,MQTT 表示报文类型也是用了 4 位,16 种组合。这一点跟 WebSocket 是一样的。MQTT 的报文类型有:
Name | Value | Direction of flow | Description |
Reserved | 0 | Forbidden | Reserved |
CONNECT | 1 | Client to Server | Connection request |
CONNACK | 2 | Server to Client | Connect acknowledgment |
PUBLISH | 3 | Client to Server or Server to Client | Publish message |
PUBACK | 4 | Client to Server or Server to Client | Publish acknowledgment (QoS 1) |
PUBREC | 5 | Client to Server or Server to Client | Publish received (QoS 2 delivery part 1) |
PUBREL | 6 | Client to Server or Server to Client | Publish release (QoS 2 delivery part 2) |
PUBCOMP | 7 | Client to Server or Server to Client | Publish complete (QoS 2 delivery part 3) |
SUBSCRIBE | 8 | Client to Server | Subscribe request |
SUBACK | 9 | Server to Client | Subscribe acknowledgment |
UNSUBSCRIBE | 10 | Client to Server | Unsubscribe request |
UNSUBACK | 11 | Server to Client | Unsubscribe acknowledgment |
PINGREQ | 12 | Client to Server | PING request |
PINGRESP | 13 | Server to Client | PING response |
DISCONNECT | 14 | Client to Server or Server to Client | Disconnect notification |
AUTH | 15 | Client to Server or Server to Client | Authentication exchange |
会话协商方式不同
WebSocket 基于 HTTP/1.1 的 Upgrade 机制协商会话,协商过程如下:
WebSocket 协商过程,来源:https://dotnetplaybook.com/which-is-best-websockets-or-signalr/
一旦完成协商,就会获得一个双工信道,可以双向传递数据。
MQTT 协议则需要通过 CONNECT 报文协商会话:
MQTT 协商会话,来源:https://medium.com/predict/an-era-of-iot-m2m-communication-protocols-mqtt-e68d81b93613
TCP连接建立之后,客户端会主动发送 CONNECT 报文。服务端准备好之后会回应 CONNACK 报文。
消息收发方式不同
WebSocket 收发消息不需要对方确认。因为底层的 TCP 协议会完成可靠传输:
WebSocket 收发消息,来源:https://www.vaadata.com/blog/websockets-security-attacks-risks/
MQTT 收发消息需要根据投递级别进行确认:
MQTT 发布确认,来源:http://www.steves-internet-guide.com/mqtt-publish-subscribe/
对于只发布一次的消息甚至需要两次确认!
保活机制不同
WebSocket 只规定了 ping/pong 两种报文,但并不强制要求定时收发心跳包。
MQTT 则有明确的心跳协商机制。协商会话使用的 CONNECT 报文包含 Keep Alive 头部信息,结构如下:
使用两个字节传输心跳间隔,单位是秒。会话协商后需要定时收发 PINGREQ 和 PINGRESP 报文。
使用场景不同
MQTT 主要应用在物联网等场景,WebSocket 因为有配套的浏览器API,主要应用在 Web 开发领域。但两者均为通用的应用层协议,可以在任何相关的场景使用。
- MQTT是为了物联网场景设计的基于TCP的Pub/Sub协议,有许多为物联网优化的特性,比如适应不同网络的QoS、层级主题、遗言等等。
- WebSocket是为了HTML5应用方便与服务器双向通讯而设计的协议,HTTP握手然后转TCP协议,用于取代之前的Server Push、Comet、长轮询等老旧实现。
两者之所有有交集,是因为一个应用场景:如何通过HTML5应用来作为MQTT的客户端,以便接受设备消息或者向设备发送信息,那么MQTT over WebSocket自然成了最合理的途径了。
总结
MQTT和WebSocket都是面向报文的二进制传输协议。WebSocket更简单,更灵活;MQTT相对复杂,但功能强大。大家可以根据自己的使用场景按需选择。
不论能不能用上,我个人都建议大家好好学习这两种协议。文本协议看HTTP,二进制协议看WebSocket和MQTT。这会为自己设计协议提供很好的参考。