点击上方“中兴开发者社区”,关注我们
每天读一篇一线开发者原创好文
在物联网领域中,MQTT和CoAP是最主要的两个应用协议。MQTT(Message Queuing Telemetry Transport/消息队列遥测传输)是基于TCP的发布/订阅方式的应用协议,没错,你可以将它类比Redis的Pub/Sub机制。CoAP(Constrained Application Protocol,资源受限应用协议)是基于UDP的请求/响应方式的应用协议,是的,你可以类比HTTP,CoAP设计的方方面面的确参考了HTTP,所以你可以把CoAP认为是“物联网的HTTP”。我之前已在《MQTT协议例析》一文中介绍了MQTT,这里在本文中我将简要介绍CoAP协议的典型功能及流程,并基于开源软件libcoap(coap-server)搭建CoAP服务器环境,采用FireFox扩展“Copper (Cu)”作为CoAP客户端产生真实消息,同时使用Wireshark对真实消息进行抓包以及进行码流分析。
首先,使用Copper (Cu)连接coap-server。CoAP默认端口为5683,在Copper (Cu)中输入“coap://<IP地址>:5683/”,并执行Discover(探索),即可发起对CoAP默认资源配置的查询,从而获得该CoAP服务器所提供的所有资源的路径。下图左侧红框内为CoAP NON GET /.well-known/core 请求消息的CoAP协议解码,下图右侧蓝框内为CoAP NON 2.05 Content link-format响应消息的CoAP协议解码,响应消息的内容即下部绿框中的文本信息就是该CoAP服务器所支持的所有资源路径。
CoAP支持四种方法GET/POST/PUT/DELETE,CoAP GET请求与HTTP GET类似,CoAP 2.05 Content响应与HTTP 200 OK类似。为什么这里CoAP请求和响应中都加上了一个“NON”来描述呢?这是因为CoAP基于UDP,UDP是不可靠连接可能丢包,所以CoAP自己实现了连接可靠性。可靠的CoAP消息为CON类型,CON类型的消息必须有响应,如果超时收不到响应就要重发。有可靠就会有不可靠,不可靠的CoAP消息为NON类型,NON类型就是指即使这条消息丢了,也不需要重发。本例的请求和响应都是NON类型的,都是无关紧要的消息。
物联网终端设备通常无法人为操作,终端需要能够自动获取服务器的资源信息,查询“/.well-known/core”就是CoAP协议规定好的用于自动查询服务器所有资源路径的方式。终端发起GET /.well-known/core用于获取该URI所代表的资源。在CoAP中URI需要以Option的形式编码,“/.well-known/core”被编码为上图左侧红框请求消息的Opt#1: Uri-Path: .well-known和Opt#2: Uri-Path: core两部分。服务器收到后会按#1、#2的顺序将其复原为正确的URI“/.well-known/core”。对于上图右侧蓝框的响应消息,服务器将回复link-format格式的文本数据,与HTTP Content-Type类似,在CoAP中通过Content-Format选项(即,上图右侧蓝框Opt #1)来指示所携带数据的类型为application/link-format格式。然后,通过分隔符255(End of options marker)分割Option与载荷部分。载荷中的内容为上图下部绿色文本形式,该文本的格式即为link-format,用于描述CoAP服务器有哪些资源以及资源路径和各种具体属性信息。
我们再来详细看看“/.well-known/core”返回的link-format数据的具体内容,如下图所示,link-format数据使用逗号分割,本例中被2个逗号分割成3个被尖括号所括的资源路径,分别是“/”、“/time”、“/async”,这三个资源有各自的属性,在link-format格式中属性用分号分割。这里提醒一下,CoAP的link-format格式中逗号、分号的用法,与我们在C/C++或者JSON中的常见用法正好相反,请一定注意。如下图所示,资源“/”的属性有title和ct,title即标题即该资源含义或内容的简要描述;ct即Content-Type,在link-format格式中0表示text/plain即纯文本格式。资源“/time”的属性有if、rt、title、ct、obs,其中obs即Observable即可观察的,其值为true,表示该资源支持观察者模式,下文将给出观察者模式的举例和解释。
下面给出CoAP观察者模式的举例,我在下面这个例子中会介绍CoAP协议的Token、分离模式、CON消息、ACK消息、RST消息、Max-Age有效期等知识。如下图所示,本例分为五个步骤,首先是CoAP客户端对 /time 资源发起申请观察请求,然后是CoAP服务器在 /time 资源内容发生变化时主动向客户端投递 /time 的最新内容,连续投递三次后,客户端通过RST消息通知服务器停止观察。为什么CoAP协议支持观察者模式呢?这是因为物联网终端设备通常需要从服务器获取最新的数据信息,如果由客户端发起周期性轮询,则可能出现两种问题:一是服务器资源长期不变,则客户端发起的多次查询请求都是无效的,浪费运算及网络资源;二是如果轮询周期设置过长,则服务器的资源在前次轮询刚过时发生了变化,则会造成客户端无法及时获悉最新的资源信息。因此,CoAP引入了观察者模式,由客户端申请观察,然后主动权就交给服务器,只有资源变化时服务器才将资源信息按需投递给客户端,从而解决上述两个问题。本例的 /time 资源用于提供服务器时间的,在coap-server的 /time 每2秒钟变化一次,因此在观察者模式中服务器会每隔2秒钟发送一次当前的时间信息给客户端。
第1步,客户端发起NON GET /time请求,在请求中携带Observe选项,选项值为0,表示客户端在服务器上注册以申请对 /time 进入观察者模式。服务器收到该请求后,将根据Token值记录该客户端的会话信息,如果 /time 有变化,则会将 /time 的最新内容投递给客户端。我们把一个客户端所注册的一次观察者过程看做一次会话,则Token就是该会话的标识ID,客户端和服务器都会根据Token来区分和识别不同消息是否属于同一个观察者会话。本步骤中服务器回复了该请求,其实对于NON类型的GET请求来说,服务器是可以不必回复的,不过回复了也没有关系。
第2步,两秒钟后,服务器的 /time 资源发生了变化,服务器主动向客户端发起CON 2.05 Content消息,携带当前最新的时间信息给客户端。因为是CON消息,所有客户端收到后必须回复一个ACK消息,如果客户端不回复ACK消息或者ACK消息在网络传输中丢失,则服务器将超时重发该CON消息。在这个服务器主动下发的CON消息中,Observe选项的值为2882,在这里Observe选项值的含义表示计数器,下一次为2883、再下一次为2884、2885、2886等。计数器有助于客户端了解观察者会话中资源的变化次数,以及辅助判断重发情况的资源数据是否为最新。在这个CON 2.05 Content消息中,时间信息的有效期 Max-age 选项值为1,该选项含义为数据的有效期,单位是秒。也就是说,1秒钟后该资源就失效了。
第3步,与第2步类似,又过了两秒钟,服务器的 /time 资源又发生了变化,服务器再次主动向客户端发起CON 2.05 Content消息,携带当前最新的时间信息给客户端,客户端回复ACK以确认。
第4步,与第3步类似,又过了两秒钟,服务器的 /time 资源又发生了变化,服务器再次主动向客户端发起CON 2.05 Content消息,携带当前最新的时间信息给客户端,客户端回复ACK以确认。
第5步,与第4步类似,又过了两秒钟,服务器的 /time 资源又发生了变化,服务器再次主动向客户端发起CON 2.05 Content消息,携带当前最新的时间信息给客户端。这次客户端希望退出观察者模式,向服务器发送RST消息,以退出该Token所标识的观察者会话。需要注意的是,退出观察者会话也可以通过GET消息的Observe选项指示退出,客户端发起的GET消息其Observe选项值为1,即表示退出观察者会话。
如上观察者模式举例中,同一个会话以相同的Token来标识,在同一个会话中有多对消息,每对消息以相同的MessageID来标识,这种同一个Token会话有多对MessageID消息的流程,称为CoAP的分离模式。观察者模式就是一种典型的分离模式。
CoAP协议是IETF制定的标准物联网应用协议,在万物互联时代尤为重要,本文结合消息码流实例抛砖引玉,介绍了CoAP协议的典型功能和流程,希望能够帮助读者了解CoAP协议之概貌,以进一步学习CoAP,了解IoT,了解万物互联。
参考资料:
1. rfc7252 The Constrained Application Protocol (CoAP)
2. rfc7959 Block-Wise Transfers in the Constrained Application Protocol (CoAP)
3. rfc8075 Guidelines for Mapping Implementations HTTP to the Constrained Application Protocol (CoAP)
4. http://coap.technology/
5. http://coap.technology/spec.html
6. https://en.wikipedia.org/wiki/Constrained_Application_Protocol
7. https://en.wikipedia.org/wiki/MQTT
8. https://libcoap.net/
拓展阅读