TCP/IP, WebSocket 和 MQTT

轉自:  http://www.cnblogs.com/shanyou/p/4085802.htmlhtml

 

 

按照OSI網絡分層模型,IP是網絡層協議,TCP是傳輸層協議,而HTTP和MQTT是應用層的協議。在這三者之間, TCP是HTTP和MQTT底層的協議。你們對HTTP很熟悉,這裏簡要介紹下MQTT。MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸)是IBM開發的一個即時通信協議,有可能成爲物聯網的重要組成部分。該協議支持全部平臺,幾乎能夠把全部聯網物品 和外部鏈接起來,被用來當作傳感器的通訊協議。web

  1. HTTP的不足

    HTTP協議通過多年的使用,發現了一些不足,主要是性能方面的,包括: 算法

    HTTP的鏈接問題,HTTP客戶端和服務器之間的交互是採用請求/應答模式,在客戶端請求時,會創建一個HTTP鏈接,而後發送請求消息,服務端給出應答消息,而後鏈接就關閉了。(後來的HTTP1.1支持持久鏈接)
    由於TCP鏈接的創建過程是有開銷的,若是使用了SSL/TLS開銷就更大。
    瀏覽器

    在瀏覽器裏,一個網頁包含許多資源,包括HTML,CSS,JavaScript,圖片等等,這樣在加載一個網頁時要同時打開鏈接到同一服務器的多個鏈接。 安全

    HTTP消息頭問題,如今的客戶端會發送大量的HTTP消息頭,因爲一個網頁可能須要50-100個請求,就會有至關大的消息頭的數據量。 服務器

    HTTP通訊方式問題,HTTP的請求/應答方式的會話都是客戶端發起的,缺少服務器通知客戶端的機制,在須要通知的場景,如聊天室,遊戲,客戶端應用須要不斷地輪詢服務器。 websocket

    而 WebSocket是從不一樣的角度來解決這些不足中的一部分。還有其餘技術也在針對這些不足提出改進。 網絡

  2. WebSocket
    WebSocket則提供使用一個TCP鏈接進行雙向通信的機制,包括網絡協議和API,以取代網頁和服務器採用HTTP輪詢進行雙向通信的機制。

    本質上來講,WebSocket是不限於 HTTP協議的,可是因爲現存大量的HTTP基礎設施,代理,過濾,身份認證等等,WebSocket借用HTTP和HTTPS的端口。因爲使用HTTP 的端口,所以TCP鏈接創建後的握手消息是基於HTTP的,由服務器判斷這是一個HTTP協議,仍是WebSocket協議。 WebSocket鏈接除了創建和關閉時的握手,數據傳輸和HTTP沒丁點關係了。 session

歷時11年,WebSocket終於被批准成爲IETF的建議標準:RFC6455.其前身是WHATWG Web Hypertext Application Technology Working Group)的工做。而Web SocketAPI,W3C的工做。socket

WebSocket能夠只打開一個到服務器的連接,而且在此連接上交換信息。其優點在於減小了傳統方法的複雜性,提升了可靠性和下降了瀏覽器和客戶端之間的負載。這樣作的一個重要緣由是,不少防火牆屏蔽80之外的端口,迫使愈來愈多的應用遷移到HTTP上來了。

11年的websocket草案的變遷中,有的瀏覽器支持的是舊版本的websocket,好比iPhone4上的safari使用的WebSocket是舊版的握手協議,那麼就要使用就的握手協議來製作服務器端。現在只有Safari支持舊版本的協議,ChromeFirefox最新版都已升級至Hybi-10協議地址)。所以,咱們再來看一下WebSocket新版協議Hybi-10。此次協議變動很是大,主要集中在握手協議和數據傳輸的格式上。

握手協議

咱們先來看一下大體的區別:

  1. 最老的websocket草案標準中是沒有安全key,草案7.57.6中有兩個安全key,而如今的草案10中只有一個安全key,即將 7.57.6http頭中的"Sec-WebSocket-Key1″"Sec-WebSocket-Key2″合併爲了一個"Sec- WebSocket-Key"
  2. http頭中Upgrade的值由"WebSocket"修改成了"websocket"http頭中的"-Origin"修改成了"Sec-WebSocket-Origin";
  3. 增長了http"Sec-WebSocket-Accept",用來返回原來草案7.57.6服務器返回給客戶端的握手驗證,原來是之內容的形式返回,如今是放到了http頭中;另外服務器返回客戶端的驗證方式也有變化。

服務器生成驗證的方式變化較大,咱們來作一介紹。

舊版:

1 GET / HTTP/1.1
2 Upgrade: WebSocket
3 Connection: Upgrade
4 Host: 127.0.0.1:1337
5 Origin: http://127.0.0.1:8000
6 Cookie: sessionid=xxxx; calView=day; dayCurrentDate=1314288000000
7 Sec-WebSocket-Key1: cV`p1* 42#7  ^9}_ 647  08{
8 Sec-WebSocket-Key2: O8 415 8x37R A8   4
9 ;"######

舊版生成Token的方法以下:

取出Sec-WebSocket-Key1中的全部數字字符造成一個數值,這裏是1427964708,而後除以Key1中的空格數目,獲得一個數值,保留該數值整數位,獲得數值N1;對Sec-WebSocket-Key2採起一樣的算法,獲得第二個整數N2;把N1N2按照Big- Endian字符序列鏈接起來,而後再與另一個Key3鏈接,獲得一個原始序列ser_keyKey3是指在握手請求最後,有一個8字節的奇怪的字符";"######",這個就是Key3。而後對ser_key進行一次md5運算得出一個16字節長的digest,這就是老版本協議須要的 token,而後將這個token附在握手消息的最後發送回Client,便可完成握手。

新版:

1 GET / HTTP/1.1
2 Upgrade: websocket
3 Connection: Upgrade
4 Host: 127.0.0.1:1337
5 Sec-WebSocket-Origin: http://127.0.0.1:8000
6 Sec-WebSocket-Key: erWJbDVAlYnHvHNulgrW8Q==
7 Sec-WebSocket-Version: 8
8 Cookie: csrftoken=xxxxxx; sessionid=xxxxx

新版生成Token的方法以下:

首先服務器將key(長度24)截取出來,如4tAjitqO9So2Wu8lkrsq3w==,用它和自定義的一個字符串(長度 36258EAFA5-E914-47DA-95CA-C5AB0DC85B11鏈接起來,而後把這一字符串進行SHA-1算法加密,獲得長度爲20節的二進制數據,再將這些數據通過Base64編碼,最終獲得服務端的密鑰,也就是ser_key。服務器將ser_key附在返回值Sec- WebSocket-Accept後,至此握手成功。

WebSocket也有本身一套幀協議。數據報文格式以下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

      0                   1                   2                   3

      01234567890123456789012345678901

     +-+-+-+-+-------+-+-------------+-------------------------------+

     |F|R|R|R|opcode|M|Payload len|    Extended payload length    |

     |I|S|S|S|  (4)  |A|     (7)     |             (16/63)           |

     |N|V|V|V|       |S|             |   (ifpayload len==126/127)   |

     ||1|2|3|       |K|             |                               |

     +-+-+-+-+-------+-+-------------+---------------+

     |     Extended payload length continued,ifpayload len==127  |

     +---------------+-------------------------------+

     |                               |Masking-key,ifMASK set to1  |

     +-------------------------------+-------------------------------+

     |Masking-key(continued)       |          Payload Data         |

     +-----------------------------------------------+

     :                     Payload Data continued...                :

     +-------------------------------+

     |                     Payload Data continued...                |

     +---------------------------------------------------------------+

FIN1位,用來代表這是一個消息的最後的消息片段,固然第一個消息片段也多是最後的一個消息片段;

RSV1, RSV2, RSV3: 分別都是1位,若是雙方之間沒有約定自定義協議,那麼這幾位的值都必須爲0,不然必須斷掉WebSocket鏈接;

Opcode:4位操做碼,定義有效負載數據,若是收到了一個未知的操做碼,鏈接也必須斷掉,如下是定義的操做碼:

  • %x0 表示連續消息片段
  • %x1 表示文本消息片段
  • %x2 表未二進制消息片段
  • %x3-7 爲未來的非控制消息片段保留的操做碼
  • %x8 表示鏈接關閉
  • %x9 表示心跳檢查的ping
  • %xA 表示心跳檢查的pong
  • %xB-F 爲未來的控制消息片段的保留操做碼

Mask:1位,定義傳輸的數據是否有加掩碼,若是設置爲1,掩碼鍵必須放在masking-key區域,客戶端發送給服務端的全部消息,此位的值都是1

Payload length: 傳輸數據的長度,以字節的形式表示:7位、7+16位、或者7+64位。若是這個值以字節表示是0-125這個範圍,那這個值就表示傳輸數據的長度;若是這個值是126,則隨後的兩個字節表示的是一個16進制無符號數,用來表示傳輸數據的長度;若是這個值是127,則隨後的是8個字節表示的一個64位無符合數,這個數用來表示傳輸數據的長度。多字節長度的數量是以網絡字節的順序表示。負載數據的長度爲擴展數據及應用數據之和,擴展數據的長度可能爲0,於是此時負載數據的長度就爲應用數據的長度。

Masking-key:04個字節,客戶端發送給服務端的數據,都是經過內嵌的一個32位值做爲掩碼的;掩碼鍵只有在掩碼位設置爲1的時候存在。
Payload data:  (x+y)位,負載數據爲擴展數據及應用數據長度之和。
Extension data:x位,若是客戶端與服務端之間沒有特殊約定,那麼擴展數據的長度始終爲0,任何的擴展都必須指定擴展數據的長度,或者長度的計算方式,以及在握手時如何肯定正確的握手方式。若是存在擴展數據,則擴展數據就會包括在負載數據的長度以內。
Application data:y位,任意的應用數據,放在擴展數據以後,應用數據的長度=負載數據的長度-擴展數據的長度。

3、 MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸)是輕量級基於代理的發佈/訂閱的消息傳輸協議,設計思想是開放、簡單、輕量、易於實現。這些特色使它適用於受限環境。例如,但不只限於此:

  • 網絡代價昂貴,帶寬低、不可靠。
  • 在嵌入設備中運行,處理器和內存資源有限。

該協議的特色有:

  • 使用發佈/訂閱消息模式,提供一對多的消息發佈,解除應用程序耦合。
  • 對負載內容屏蔽的消息傳輸。
  • 使用 TCP/IP 提供網絡鏈接。
  • 有三種消息發佈服務質量:
  • "至多一次",消息發佈徹底依賴底層 TCP/IP 網絡。會發生消息丟失或重複。這一級別可用於以下狀況,環境傳感器數據,丟失一次讀記錄無所謂,由於不久後還會有第二次發送。
  • "至少一次",確保消息到達,但消息重複可能會發生。
  • "只有一次",確保消息到達一次。這一級別可用於以下狀況,在計費系統中,消息重複或丟失會致使不正確的結果。
  • 小型傳輸,開銷很小(固定長度的頭部是 2 字節),協議交換最小化,以下降網絡流量。
  • 使用 Last Will 和 Testament 特性通知有關各方客戶端異常中斷的機制。

早在1999年,IBM的Andy Stanford-Clark博士以及Arcom公司ArlenNipper博士發明了MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸)技術。BM和St. Jude醫療中心經過MQTT開發了一套Merlin系統,該系統使用了用於家庭保健的傳感器。St. Jude醫療中心設計了一個叫作Merlin@home的心臟裝置,這種無限發射器能夠用來監控那些已經植入復律-除顫器和起搏器(二者都是基本的傳感 器)的心臟病人。

該產品利用MQTT把病人的即時更新信息傳給醫生/醫院,而後醫院進行保存。這樣的話,病人就不用親自去醫院檢查心臟儀器了,醫生能夠隨時查看病人的數據,給出建議,病人在家裏就能夠自行檢查。

IBM稱該發射器包括一個大型觸摸屏,一個嵌入式鍵盤平臺,以及一個Linux操做系統。

在將來幾年,MQTT的應用會愈來愈廣,值得關注。

經過MQTT協議,目前已經擴展出了數十個MQTT服務器端程序,能夠經過PHP,JAVA,Python,C,C#等系統語言來向MQTT發送相關消息。

此外,國內不少企業都普遍使用MQTT做爲 Android手機客戶端與服務器端推送消息的協議。其中Sohu,Cmstop手機客戶端中均有使用到MQTT做爲消息推送消息。據Cmstop主要負 責消息推送的高級研發工程師李文凱稱,隨着移動互聯網的發展,MQTT因爲開放源代碼,耗電量小等特色,將會在移動消息推送領域會有更多的貢獻,在物聯網 領域,傳感器與服務器的通訊,信息的收集,MQTT均可以做爲考慮的方案之一。在將來MQTT會進入到咱們生活的各各方面。

若是須要下載MQTT服務器端,能夠直接去MQTT官方網站點擊software進行下載MQTT協議衍生出來的各個不一樣版本。

MQTTTCPWebSocket的關係能夠用下圖一目瞭然:

MQTT協議專一於網絡、資源受限環境,創建 之初未曾考慮WEB環境。HTML5 Websocket是創建在TCP基礎上的雙通道通訊,和TCP通訊方式很相似,適用於WEB瀏覽器環境。雖然MQTT基因層面選擇了TCP做爲通訊通 道,但咱們添加個編解碼方式,MQTT over Websocket也能夠的。這樣作的好處,MQTT的使用範疇被擴展到HTML五、桌面端瀏覽器、移動端WebApp、Hybrid等,多了一些想像空 間。這樣看來,不管是移動端,仍是WEB端,MQTT都會有本身的使用空間。

相關文章
相關標籤/搜索