存活 和 客户端接管 - MQTT 核心:第十章
欢迎来到MQTT核心系列的第十章。这个系列一共有十章,用来介绍MQTT的核心特性和概念。在这章中,我们将讨论MQTT的存活特性并且说明为什么这个特性对于移动网络是至关重要的。
半开放TCP连接的问题
MQTT是基于TCP(Transmission Control Protocol)协议的。这个协议能保证数据包能在网络中以一种可靠,有序,检错的方式传输。但是通讯双方有可能会出现不同步的情况。例如,其中一方崩溃或者发生传输错误,在TCP中,这种未完成的连接状态叫做半开放连接。要记住的重要一点是,通信的一侧继续起作用,而没有通知另一侧发生故障。仍处于连接状态的一方将继续尝试发送消息并等待确认。
正如安迪·斯坦福-克拉克(MQTT协议的发明者)所说,半开连接的问题在移动网络中会更加常见:
虽然理论上TCP / IP在套接字中断时会通知您,但实际上,尤其是在移动和卫星链路之类的东西上,它们经常通过空中“伪造” TCP并在每个末端放回标头,对于TCP而言,这很有可能会话到“黑洞”,即它似乎仍在打开,但实际上只是将您写入它的所有内容都丢到了地板上
只要消息发送频繁且没有超过存活时间,那么就没有必要发送额外的消息来保证连接的开启状态。
如果客户端在一个存活时间周期内没有发送消息,那么它就必须发送一个PINGREQ数据包给代理,以相互确认对方的存活。
在一个半存活时间周期内没有收到客户端的消息或者PINGREQ数据包后,代理必须断开与这个客户端的连接。同样,客户端在一个合理的时间内没有收到代理的响应,客户端也应该断开与代理的连接。
存活机制流程
让我们来近距离看看存活消息。存活机制会用到两种数据包:
PINGREQ
PINGREQ消息是由客户端发送的,用来告诉代理客户端存活。假如客户端没有发送任何其它类型的数据包(例如,PUBLISH或者 SUBSCRIBE),客户端必须发送一个PINGREQ包给代理。客户端可以在任何时候发送一个PINGREQ数据包,以便确认它与代理之间的网络连接是通的。PINGREQ数据包不包含任何负载。
PINGRESP
当代理收到一个PINGREQ数据包的时候,代理必须回复一个PINGRESP的数据包来告诉客户端自己依然存活。PINGRESP数据包不包含负载。
乐而闻道
-
如果代理没有接收到PINGREQ或者其它的数据包,那么代理将关闭连接并且发送遗言(如果客户端指定了遗言)。
-
客户端负责设置合适的存活时间间隔。例如,客户端可以根据信号的强度来调整存活时间间隔。
-
最大存活时间间隔是18h12min15s
-
如果将存活时间间隔设置为0,那么存活机制将失效
客户端接管
通常,一个断连的客户端会尝试重新连接。但有时,代理任然对这个客户端保持着半开连接。在MQTT中,如果代理发现了半开连接,它就会实行客户端接管。代理会关闭这个客户端之前的连接,并且建立一个新的连接。这种行为确保了半开连接不会阻止断连的客户端重新连接。
这就是第十章所有的内容了。我们希望你能喜欢着整个系列。虽然这章是这个系列最后一章,但是我们还有一些补充,请看下一章。