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/。