Ajax、Comet與Websocket

從 http 協議提及javascript

1996年IETF  HTTP工做組發佈了HTTP協議的1.0版本 ,到如今廣泛使用的版本1.1,HTTP協議經歷了17 年的發展。這種分佈式、無狀態、基於TCP的請求/響應式、在互聯網盛行的今天獲得普遍應用的協議,相對於互聯網的迅猛發展,它彷佛進步地很慢。互聯網從興起到如今,經歷了門戶網站盛行的web1.0時代,然後隨着ajax技術的出現,發展爲web應用盛行的web2.0時代,現在又朝着web3.0的方向邁進。反觀http協議,從版本1.0發展到1.1,除了默認長鏈接以外就是緩存處理、帶寬優化和安全性等方面的不痛不癢的改進。它一直保留着無狀態、請求/響應模式,彷佛曆來沒意識到這應該有所改變。html

 

Ajax--- 腳本發送的 http 請求html5

傳統的web應用要想與服務器交互,必須提交一個表單(form),服務器接收並處理傳來的表單,而後返回全新的頁面,由於先後兩個頁面的數據大部分都是相同的,這個過程傳輸了不少冗餘的數據、浪費了帶寬。因而Ajax技術便應運而生。java

Ajax是 Asynchronous JavaScript and XML 的簡稱,由Jesse James Garrett 首先提出。這種技術開創性地容許瀏覽器腳本(JS)發送http請求。Outlook Web Access小組於98年使用,並很快成爲IE4.0的一部分,可是這個技術一直很小衆,直到2005年初,google在他的goole groups、gmail等交互式應用中普遍使用此種技術,才使得Ajax迅速被你們所接受。web

Ajax的出現使客戶端與服務器端傳輸數據少了不少,也快了不少,也知足了以豐富用戶體驗爲特色的web2.0時代 初期發展的須要,可是慢慢地也暴露了他的弊端。好比沒法知足即時通訊等富交互式應用的實時更新數據的要求。這種瀏覽器端的小技術畢竟仍是基於http協議,http協議要求的請求/響應的模式也是沒法改變的,除非http協議自己有所改變。ajax

 

Comet--- 一種 hack 技術瀏覽器

以即時通訊爲表明的web應用程序對數據的Low Latency要求,傳統的基於輪詢的方式已經沒法知足,並且也會帶來很差的用戶體驗。因而一種基於http長鏈接的「服務器推」技術便被hack出來。這種技術被命名爲 Comet ,這個術語由Dojo Toolkit 的項目主管Alex Russell在博文 Comet: Low Latency Data for the Browser 首次提出,並沿用下來。緩存

其實,服務器推很早就存在了,在經典的client/server模型中有普遍使用,只是瀏覽器太懶了,並無對這種技術提供很好的支持。可是Ajax的出現使這種技術在瀏覽器上實現成爲可能, google的gmail和gtalk的整合首先使用了這種技術。隨着一些關鍵問題的解決(好比 IE 的加載顯示問題),很快這種技術獲得了承認,目前已經有不少成熟的開源Comet框架。安全

如下是典型的Ajax和Comet數據傳輸方式的對比,區別簡單明瞭。典型的Ajax通訊方式也是http協議的經典使用方式,要想取得數據,必須首先發送請求。在Low Latency要求比較高的web應用中,只能增長服務器請求的頻率。Comet則不一樣,客戶端與服務器端保持一個長鏈接,只有客戶端須要的數據更新時,服務器才主動將數據推送給客戶端。服務器

Comet的實現主要有兩種方式:

  1. 基於Ajax的長輪詢(long-polling)方式

瀏覽器發出XMLHttpRequest 請求,服務器端接收到請求後,會阻塞請求直到有數據或者超時才返回,瀏覽器JS在處理請求返回信息(超時或有效數據)後再次發出請求,從新創建鏈接。在此期間服務器端可能已經有新的數據到達,服務器會選擇把數據保存,直到從新創建鏈接,瀏覽器會把全部數據一次性取回。

2.  基於 Iframe 及 htmlfile 的流(http streaming)方式

Iframe是html標記,這個標記的src屬性會保持對指定服務器的長鏈接請求,服務器端則能夠不停地返回數據,相對於第一種方式,這種方式跟傳統的服務器推則更接近。

在第一種方式中,瀏覽器在收到數據後會直接調用JS回調函數,可是這種方式該如何響應數據呢?能夠經過在返回數據中嵌入JS腳本的方式,如「<script type="text/javascript">js_func(「data from server 」)</script>」,服務器端將返回的數據做爲回調函數的參數,瀏覽器在收到數據後就會執行這段JS腳本。

可是這種方式有一個明顯的不足之處:IE、Morzilla Firefox 下端的進度欄都會顯示加載沒有完成,並且 IE 上方的圖標會不停的轉動,表示加載正在進行。Google 的天才們使用一個稱爲 「htmlfile」 的 ActiveX 解決了在 IE 中的加載顯示問題,並將這種方法應用到了 gmail+gtalk 產品中。

Websocket--- 將來的解決方案

         若是說Ajax的出現是互聯網發展的必然,那麼Comet技術的出現則更多透露出一種無奈,僅僅做爲一種hack技術,由於沒有更好的解決方案。Comet解決的問題應該由誰來解決纔是合理的呢?瀏覽器,html標準,仍是http標準?主角應該是誰呢?本質上講,這涉及到數據傳輸方式,http協議應首當其衝,是時候改變一下這個懶惰的協議的請求/響應模式了。

W3C給出了答案,在新一代html標準html5中提供了一種瀏覽器和服務器間進行全雙工通信的網絡技術Websocket。從Websocket草案得知,Websocket是一個全新的、獨立的協議,基於TCP協議,與http協議兼容、卻不會融入http協議,僅僅做爲html5的一部分。因而乎腳本又被賦予了另外一種能力:發起websocket請求。這種方式咱們應該很熟悉,由於Ajax就是這麼作的,所不一樣的是,Ajax發起的是http請求而已。 

與http協議不一樣的請求/響應模式不一樣,Websocket在創建鏈接以前有一個Handshake(Opening Handshake)過程,在關閉鏈接前也有一個Handshake(Closing Handshake)過程,創建鏈接以後,雙方便可雙向通訊。

Opening Handshake

    客戶端發起鏈接Handshake請求

GET /chat HTTP/1.1

        Host: server.example.com

        Upgrade: websocket

        Connection: Upgrade

        Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

        Origin: http://example.com

        Sec-WebSocket-Protocol: chat, superchat

        Sec-WebSocket-Version: 13

         服務器端響應:

        HTTP/1.1 101 Switching Protocols

        Upgrade: websocket

        Connection: Upgrade

        Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

        Sec-WebSocket-Protocol: chat

「Upgrade:WebSocket」表示這是一個特殊的 HTTP 請求,請求的目的就是要將客戶端和服務器端的通信協議從 HTTP 協議升級到 WebSocket 協議。

「Sec-WebSocket-Key」是一段瀏覽器base64加密的密鑰

「Sec-WebSocket-Accept」服務器端在接收到的Sec-WebSocket-Key密鑰後追加一段神奇字符串「258EAFA5-E914-47DA-95CA-C5AB0DC85B11」,並將結果進行sha-1哈希,而後再進行base64加密返回給客戶端。

「Sec-WebSocket-Protocol」表示客戶端請求提供的可供選擇的子協議,及服務器端選中的支持的子協議,「Origin」服務器端用於區分未受權的websocket瀏覽器

「HTTP/1.1 101 Switching Protocols」中101爲服務器返回的狀態碼,全部非101的狀態碼都表示handshake並未完成。

 

Data Framing

Websocket協議經過序列化的數據包傳輸數據。數據封包協議中定義了opcode、payload length、Payload data等字段。具體封包格式以下圖所示:

FIN: 標識是否爲此消息的最後一個數據包,佔 1 bit

RSV1, RSV2, RSV3:  用於擴展協議,通常爲0,各佔1bit

Opcode:數據包類型(frame type),佔4bits

         0x0:標識一箇中間數據包

         0x1:標識一個text類型數據包

         0x2:標識一個binary類型數據包

         0x3-7:保留

         0x8:標識一個斷開鏈接類型數據包

         0x9:標識一個ping類型數據包

         0xA:表示一個pong類型數據包

         0xB-F:保留

Payload length:Payload data的長度,佔7bits,若是這個值等於126,則此後16bits用於表示Payload length,若是這個值等於127,則此後64bits用於表示Payload length

Payload data:應用層數據

Closing Handshake

相對於Opening Handshake,Closing Handshake則簡單得多,主動關閉的一方向另外一方發送一個關閉類型的數據包,對方收到此數據包以後,再回復一個相同類型的數據包,關閉完成。

關閉類型數據包遵照封包協議,Opcode爲0x8,Payload data能夠用於攜帶關閉緣由或消息。 

雖然現階段websocket協議還處於草案階段,不過瀏覽器早就開始開始支持了,如下是不一樣瀏覽器兼容列表:

 

Feature

Chrome

Firefox (Gecko)

Internet Explorer

Opera

Safari

Version -76 support Obsolete

6

4.0 (2.0)

Not supported

11.00 (disabled)

5.0.1

Protocol version 7 support Obsolete

Not supported

6.0 (6.0) 
Moz

Not supported

Not supported

Not supported

Protocol version 10 support Obsolete

14

7.0 (7.0) 
Moz

HTML5 Labs

?

?

Standard - RFC 6455 Support

16

11.0 (11.0)

10

12.10

6.0

從瀏覽器支持角度來看,websocket還有很長的路要走,特別是在中國這個IE6依然盛行的國家,即使在websocket標準化以後,舊版本瀏覽器的消亡也須要很長一段時間,所以現階段comet依然是最好的解決方案。

相關文章
相關標籤/搜索