1、物联网应用层协议介绍
在移动互联网中,最常用的应用层协议就是HTTP协议,HTTP协议同样可以用于物联网系统中。HTTP协议采取的是请求-响应(Request-Response)的通信机制,服务器没有办法主动给客户端发送消息。如果要实现这种消息推送,就需要借助WebSocket这种全双工的通信机制。不过对于很多计算和存储资源有限的物联网节点,不太适合使用HTTP协议。除了HTTP协议以外,也有很多更适合于物联网应用的协议,比如MQTT、 DDS、 AMQP、XMPP、 JMS、 REST、 CoAP等。
发布-订阅机制是各个物联网软件平台最常使用的物联网协议,很多物联网应用层协议都是基于发布-订阅(Publish-Subscribe)机制,这种机制非常适合物联网系统应用。MQTT协议、STOMP协议、AMQP协议以及DDS协议都属于这种发布-订阅的机制。
每个传感器节点,采集的数据需要上传到网络,相当于是一个消息的发布,这个消息需要基于某个主题,比如传感器的类型。所有关心这个主题的节点,都可以通过订阅这个主题的消息,实时获取最新的数据。
DDS、MQTT、AMQP和JMS都是基于发布/订阅模式,发布/订阅框架具有服务自发现、动态扩展、事件过滤的特点,它解决了物联网系统在应用层的数据源快速获取、物的加入和退出、兴趣订阅、降低带宽流量等问题,实现物的联接在空间上松耦合(双方无需知道通信地址)、时间上松耦合和同步松耦合。
MQTT、 DDS、 AMQP、XMPP、 JMS、 REST、 CoAP这几种协议都已被广泛应用,并且每种协议都有至少10种以上的代码实现,都宣称支持实时的发布/订阅的物联网协议,但是在具体物联网系统架构设计时,需考虑实际场景的通信需求,选择合适的协议。
以智能家居为例,说明下这些协议侧重应用方向。智能家居中智能灯光控制,可以使用XMPP协议控制灯的开关;智能家居的电力供给,发电厂的发动机组的监控可以使用DDS协议;当电力输送到千家万户时,电力线的巡查和维护,可以使用MQTT协议;家里的所有电器的电量消耗,可以使用AMQP协议,传输到云端或家庭网关中进行分析;最后用户想把自家的能耗查询服务公布到互联网上,那么可以使用REST/HTTP来开放API服务。
2、应用层常用协议
2.1、HTTP协议
HTTP协议是典型的CS通讯模式,由客户端主动发起连接,向服务器请求XML或JSON数据。该协议最早是为了适用web浏览器的上网浏览场景和设计的,目前在PC、手机、pad等终端上都应用广泛,但并不适用于物联网场景。
HTTP协议在物联网场景中其有三大弊端:
(1)由于必须由设备主动向服务器发送数据,难以主动向设备推送数据。
(2)安全性不高。
(3)不同于用户交互终端如pc、手机,物联网场景中的设备多样化,对于运算和存储资源都十分受限的设备,http协议实现、XML/JSON数据格式的解析,都是不可能的任务。
REST/HTTP(松耦合服务调用):REST/HTTP其实是互联网中服务调用API封装风格,物联网中数据采集到物联网应用系统中,在物联网应用系统中,可以通过开放REST API的方式,把数据服务开放出去,被互联网中其他应用所调用。
以上的分析都是将移动互联网的技术运用到物联网,其都有一个特定就是建立连接时会传送URL地址,由两个角色是客户端和服务器,这种架构我们一般称为是RESTful架构(另外,还有SOAP 面向应用的web services架构)。
RESTful架构在互联网得到越来越广泛的运用,但物联网除了互联之外,还有其独有的特征,就是其终端设备的资源有限、低功耗运用场景、网络连接环境差(时不时断开连接)等。用C语言模拟的方式来使用RESTful架构(如Websocket)会使得终端的负荷较重,而且服务器发给终端设备的消息有可能因为断开连接而收不到。
适用范围:REST/HTTP主要为了简化互联网中的系统架构,快速实现客户端和服务器之间交互的松耦合,降低了客户端和服务器之间的交互延迟。因此适合在物联网的应用层面,通过REST开放物联网中资源,实现服务被其他应用所调用。
浏览器使用HTML文本标记语言,即浏览器通过HTTP协议向服务器发起请求(请求内容包括URL,即我们常说的网址),服务器将URL对应的HTML内容通过HTTP协议作为响应传送回给浏览器。
(1)手机端:微信端因为有内置浏览器,其天然支持前端页面。
(2)云端对手机端推送:云端使用JSP/PHP等技术开发设计前端网页和简单的逻辑即可。
(3)设备端:设备端上线时或者访问服务端参数等内容时需要模拟HTTP协议(C语言)向服务器发起请求,而请求的格式一般不使用HTML,而是使用较为简单的XML或者JSON协议格式。
(4)云端对设备端推送:云端使用HttpServlet(即使用http协议的servlet)对设备的HTTP请求进行响应,回复XML或者JSON格式的消息。
缺点:这种方式通信方式的特点就是一请求一响应,总是要客户端向服务器发出请求,服务器才给予响应。服务器从来都不会主动给客户端发消息,而且在客户端发出请求后,服务器也只是回复一次。这种HTTP单向通信方式在互联网领域发挥巨大的作用,就是服务器端可以是无状态的,极大地简化了服务器的服务流程,提高效率。但在物联网领域,我们要求的是双向的通信能力。服务端要能主动给设备端或者手机发出消息。
在这种模式下,我们怎么做双向通信呢?唯一的做法就是客户端不断地发出请求(或者周期性),服务器不断地给予回复。这种模式下的缺点显而易见:
(1)一是网络负载重,服务器每次响应后都会关闭连接,所以每次通信都得重新握手。HTTP协议的头内容的长度可不小。
(2)二是实时性差。一般设备端都是周期性地轮询服务器是否有新的消息,轮询的方式是不能获得好的实时性的。
(3)浏览器端每次发出请求是以HTML全部内容来响应的,消息长度过大,在这种情况下,会发现浏览器页面不断地刷新。
2.2、MQTT协议
消息队列遥测传输协议(MQTT : Message Queuing Telemetry Transport)是为大量计算能力有限,工作带宽有限、网络环境不可靠的传感器或控制器而设计的协议。
MQTT协议原来是IBM开发的一个即时通讯协议,基于TCP协议实现,相比来说比较适合物联网场景的通讯协议。MQTT客户端需要通过消息代理(MQTT Broker)来进行消息的发布和订阅。
MQTT协议采用发布/订阅模式,所有的物联网终端都通过TCP连接到云端,云端通过主题的方式管理各个设备关注的通讯内容,负责将设备与设备之间消息的转发。
MQTT协议的兼容性非常好,几乎支持所有平台,可以把各种物联网设备都连接起来。所以MQTT协议也是目前应用最广泛的物联网应用层协议。
MQTT有三个角色,包括服务器代理、订阅者和发布者。
(1)启动服务器代理。
(2)订阅者向服务器代理订阅相关主题。
(3)发布者向服务器代理发布主题信息。
(4)服务器代理想所有订阅该主题的订阅者推送消息。
MQTT有C/C++语言和JAVA包实现。需要明确的是,MQTT更适用于设备终端和手机APP socket通信,而不能支持浏览器使用。如果要支持微信浏览器应用,还需要增加类似WebsocketServlet技术给浏览器提供支持,这时MQTT以JS接口进行封装,并被调用完成消息推送。
适用范围:在低带宽、不可靠的网络下提供基于云平台的远程设备的数据传输和监控。MQTT协议一般适用于设备数据采集到端(Device-》Server,Device-》Gateway),集中星型网络架构(hub-and-spoke),不适用设备与设备之间通信,设备控制能力弱,另外实时性较差,一般都在秒级。
2.3、CoAP协议
受限应用协议(CoAP:Constrained Application Protocol)是6LowPAN协议栈中的应用层协议,基于REST(表述性状态传递)架构风格,支持REST交互。
CoAP是受限制的应用协议(ConstrainedApplication Protocol)的代名词。其基于UDP协议,也就是在设备终端上只需要底层实现UDP协议,而不需要实现较为复杂的TCP协议。这种协议用得比较少。
CoAP基于UDP协议,其设计初衷就是尽可能地方便地转换为HTTP协议。CoAP让用户可以像使用HTTP协议一样,在资源受限的物联网设备中使用CoAP协议。
适用范围:CoAP是简化了HTTP协议的RESTful API,CoAP是6LowPAN协议栈中的应用层协议,它适用于在资源受限的通信的IP网络。
2.4、AMQP协议
高级消息队列协议(AMQP:Advanced Message Queuing Protocol)是一个提供统一消息服务的应用层标准高级消息队列协议,为面向消息的中间件设计,这是OASIS组织提出的,该组织曾提出OSLC(Open Source Lifecyle)标准,用于业务系统例如PLM,ERP,MES等进行数据交换。
AMQP的工作原理与MQTT类似,也是基于发布-订阅机制。消息代理Broker的交换机组件(Exchange)会把接收到的消息,根据消息的主题,分配到不同的队列中,以便订阅者接收。
RabbitMQ就是在AMQP协议基础上实现的一个消息系统,遵循Mozilla Public License开源协议。RabbitMQ在互联网应用中常被用作消息服务器。
适用范围:最早应用于金融系统之间的交易消息传递,在物联网应用中,主要适用于移动手持设备与后台数据中心的通信和分析。
2.5、STOMP协议
简单(流)文本定向消息协议(STOMP: Simple (or Streaming) Text Orientated Messaging Protocol),提供了一个可互操作的连接格式,允许STOMP客户端与任意STOMP消息代理(Broker)进行交互。
STOMP协议由于设计简单,易于开发客户端,因此在多种语言和多种平台上得到广泛地应用。当前非常流行的开源消息服务器ActiveMQ、Apollo、RabbitMQ(需要插件)都支持STOMP协议。

STOMP基于TCP协议,客户端和服务器之间的通信是通过“帧”(Frame)来实现,每个帧由多“行”(Line)组成。STOMP协议定义了帧结构。
Stomp帧格式:STOMP帧第一行是命令,紧跟着键值对形式的Header内容。然后是一个空行,最后是Body内容。
2.6、数据分发服务DDS
数据分发服务(DDS:Data Distribution Service for Real-Time Systems),是面向实时系统的数据分布服务,这是大名鼎鼎的OMG组织提出的协议,其权威性应该能证明该协议的未来应用前景。

适用范围:分布式高可靠性、实时传输设备数据通信。目前DDS已经广泛应用于国防、民航、工业控制等领域。
点评:DDS很好地支持设备之间的数据分发和设备控制,设备和云端的数据传输,同时DDS的数据分发的实时效率非常高,能做到秒级内同时分发百万条消息到众多设备。DDS在服务质量(QoS)上提供非常多的保障途径,这也是它适用于国防军事、工业控制这些高可靠性、可安全性应用领域的原因。但这些应用都工作在有线网络下,在无线网络,特别是资源受限的情况下,没有见到过实施案例。
2.7、XMPP协议
XMPP(Extensible Messaging and Presence Protocol)可扩展通讯和表示协议,XMPP的前身是Jabber,一个开源形式组织产生的网络即时通信协议。XMPP目前被IETF国际标准组织完成了标准化工作。
适用范围:即时通信的应用程序,还能用在网络管理、内容供稿、协同工具、档案共享、游戏、远端系统监控等。
点评:XMPP是基于XML的协议,由于其开放性和易用性,在互联网及时通讯应用中运用广泛。相对HTTP,XMPP在通讯的业务流程上是更适合物联网系统的,开发者不用花太多心思去解决设备通讯时的业务通讯流程,相对开发成本会更低。但是HTTP协议中的安全性以及计算资源消耗的硬伤并没有得到本质的解决。
服务质量(QoS)是物联网通信中的重要考虑因素,在服务策略的帮助下,DDS能够有效地控制和管理网络带宽、内存空间等资源的使用,同时也能控制数据的可靠性、实时性和数据的生存时间,通过灵活使用这些服务质量策略,DDS不仅能在窄带的无线环境上,也能在宽带的有线通信环境上开发出满足实时性需求的数据分发系统
2.8、Ajax轮询
Ajax技术是浏览器支持的一种JavaScript技术。其能够局部改善用户体验技术,让用户在不察觉浏览器页面刷新的情况向服务器发出请求,并获得响应。其原理是:
(1)微信浏览器发出URL页面请求,服务器响应HTML页面内容。
(2)HTML页面使用js调用XMLHttpRequest来向服务器发出异步通信请求。
(3)服务器响应XML格式数据给浏览器页面。
(4)HTML页面使用DOM模型来动态刷新页面元素。
Ajax技术是微信硬件平台框架中推荐的页面交互技术,但其本质还是遵守HTTP单向通信的规则,只是页面交互时不需要刷新整个页面。其双向通信实时性问题依然未能解决。
2.9、Websocket
Websocket是HTML5支持的一种新的协议,它能够真正支持浏览器和服务器之间进行双向通信。Tomcat7及以上版本也已经支持Websocket API。
为了能够兼容浏览器HTTP协议,Websocket规定在第一次发起请求时依然要发出符合HTTP协议规范的Header,但其Connection域的值是Upgrade,并增加Upgrade域,值是socket,即告知服务器,即将建立的通信是Websocket双向通信。服务器如果接受,会返回101给客户端进行协议切换。
接下来的通信将不再以HTTP作为传输协议,而是使用Websocket规定的数据格式进行通信,其分为控制帧和数据帧。控制帧是发出心跳帧(ping),而服务器响应pong,还有结束帧;数据帧就是真实数据格式,其格式头只有6个字节(2个字节头和4个字节的掩码),后面就是真实的数据(经过掩码转换)。比HTTP格式头的长度要小多了。
客户端和服务器之间是一直保持连接,直到close,当前期间要发发2个字节的3字节的ping帧。
可见Websocket比ajax有了极大的改进。其不仅省掉经常要连接握手,还简化的协议的格式,最重要的是实时性得到保证,因为双方是真正的全双工通信。
微信浏览器客户端支持Websocket,服务器使用Tomcat7以上的WebsocketServlet类,设备端要根据Websocket协议用C语言来模拟通信。
我们在用设备端模拟Websocket通信协议时一般会先看协议,再用HttpWatch等工具来抓包,抓到的头是GET ws://ip:port/path,如果在C语言也是这样模拟发包则会报400 bad request。因为C语言利用socket建立通信时已经利用了IP和port了,其发的第一个包的头是GET/path即可,不能在其前面加上ws://ip:port/。