MQTT 协议是建立在 TCP 协议之上的,就好比汽车地盘上有四个轮胎就能跑了,但是想要大家开车更舒服,我们还是得给底盘加个壳。
为什么要在 TCP 协议之上再封装一层 MQTT 协议呢?
举个例子,如果你要用 TCP 协议做一个即时聊天室,那么你:
- 首先写一个服务器程序,监听某个端口,这样客户端就能连接上来了。然后大家就能向你的服务器发送数据了。
- 但是你不希望随便谁都能连接你的服务器并且往你的服务器里发东西,于是你写了一个注册页面,让别人先去注册账号,然后他们在客户端创建连接时发送的第一个TCP报文必须包含了账号密码。这样当你收到第一个报文之后,你就能判断这个连接是否合法了。
- 但是发过来的账号密码,具体摆在报文什么位置,也得事先约定好吧,不然怎么知道哪几位是账号哪几位是密码,于是你要求:第一个字节为1,用来告诉你这是一个请求连接的报文。然后第二个字节是报文剩下的长度(这个没啥异议,粘包处理必备),然后是“饼干熊最帅”这样一个固定的字符串(没啥意思,就是开心),后面紧跟着就是账号,然后是密码。但是账号有多长呢,所以账号第一个字节是账号的长度,剩下才是账号内容,这样就解决了“账号有多长”的问题了,密码同理。
- 如果账号密码不匹配就断开连接并且返回一句“xxxx off”,如果创建连接后半天不发送任何东西也断开连接。
- 现在大家的客户端都连接上来了,你在服务器保存了一个`账号:socket`的map,能通过任何一个账号找到这个人的socket并向他发送信息。接下来大家要开始聊天了。
- 在聊天室中,一个人发送的消息其他人都能收到,所以你添加了聊天室的概念,用户首先去你的web页面创建聊天室,然后会得到一个聊天室的ID。然后用户要加入聊天室,必须先发送一个加入聊天室的报文。然后你要求报文第一个字节为2代表加入聊天室的请求报文,然后是报文剩余长度,然后是聊天室ID,聊天室ID有多长?我们还是用第一个字节代表长度,剩下的内容为具体ID的形式来搞定。
- 现在有多个用户加入了聊天室,其中每个用户又都加入了多个聊天室。假设现在大家在聊天室A中开始聊天。用户甲向服务器发送消息,然后你发现你不知道这条消息是请求连接还是要加入聊天室还是干啥,所以发送消息也应该定义一种报文类型。于是你要求发送消息的报文的第一个字节为3,那么这个报文是发送到哪个聊天室的呢?于是你要求报文后面跟上聊天室ID,最后是具体的消息内容。
- 服务器收到第一个字节为3的消息,就知道这是一个聊天消息。然后根据上面带的聊天室ID以及你在服务器存储的用户和聊天室的关系,找到了这个聊天室里的所有人,然后你就把消息发给这里面的所有人了。
上面这个例子,在连接服务器(检查合法性、断开连接)、订阅主题(加入聊天室)、发布消息这些过程中,你约定的报文格式和设计的服务器处理逻辑就是 MQTT 协议的内容,当然我举的例子非常粗糙
真正的MQTT协议要求的处理逻辑和报文格式都完善很多,但是协议本身还是很简单的,具体内容去看 MQTT 的文档吧。
来源:oschina
链接:https://my.oschina.net/u/697862/blog/1837793