HTML5 WebSocket

參考
阮一峰 WebSocket 教程
WebSocket 是什么原理
WebSocket 淺析

WebSocket詳解(一):初步認識WebSocket技術
WebSocket詳解(二):技術原理、代碼演示和應用案例
WebSocket詳解(三):深入WebSocket通信協議細節
WebSocket詳解(四):刨根問底HTTP與WebSocket的關系(上篇)
WebSocket詳解(五):刨根問底HTTP與WebSocket的關系(下篇)
WebSocket詳解(六):刨根問底WebSocket與Socket的關系

一、示例
var ws = new WebSocket('wss://example.com/socket'); 
// 創建安全WebSocket 連接(wss)
ws.onerror = function (error) { ... } 
// 錯誤處理
ws.onclose = function () { ... } 
// 關閉時調用
ws.onopen = function () { 
// 連接建立時調用
  ws.send("Connection established. Hello server!"); 
// 向服務端發送消息
}

ws.onmessage = function(msg) { 
// 接收服務端發送的消息
  if(msg.data instanceof Blob) { 
// 處理二進制信息
    processBlob(msg.data);
  } else {
    processText(msg.data); 
// 處理文本信息
  }
}

默認JavaScript里的WebSocket傳輸是采用字符串模式的,采用UTF-8編碼。除了動態判斷收到的數據類型,也可以使用binaryType屬性,顯式指定收到的二進制數據類型(blob對象或Arraybuffer對象,默認是blob)。

Setting binaryType to accept received binary as either 'blob' or 'arraybuffer'

// 收到的是 blob 數據
ws.binaryType = "blob";
ws.onmessage = function(e) {
  console.log(e.data.size);
};

// 收到的是 ArrayBuffer 數據
ws.binaryType = "arraybuffer";
ws.onmessage = function(e) {
  console.log(e.data.byteLength);
};
二、兼容性和socket.io
WebSocket瀏覽器支持情況

除了老而不化的Opera Mini外,所有的瀏覽器都支持WebSocket。

鑒于現在不同的平臺及瀏覽器版本對WebSocket支持的不同,有開發者做了一個叫做socket.io 的為實時應用提供跨平臺實時通信的庫,我們可以使用它完成向WebSocket的切換。socket.io 旨在使實時應用在每個瀏覽器和移動設備上成為可能,模糊不同的傳輸機制之間的差異。socket.io 的名字源于它使用了瀏覽器支持并采用的 HTML5 WebSocket 標準,因為并不是所有的瀏覽器都支持 WebSocket ,所以該庫支持一系列降級功能:

  • Websocket
  • Adobe:registered: Flash:registered: Socket
  • AJAX long polling
  • AJAX multipart streaming
  • Forever Iframe
  • JSONP Polling

在大部分情境下,你都能通過這些功能選擇與瀏覽器保持類似長連接的功能。具體細節請看Socket.io。

三、WebSocket 有沒有可能取代 AJAX ?

WebSocket的誕生本質上就是為了解決HTTP協議本身的單向性問題:請求必須由客戶端向服務端發起,然后服務端進行響應。這個Request-Response的關系是無法改變的。對于一般的網頁瀏覽和訪問當然沒問題,一旦我們需要服務端主動向客戶端發送消息時就麻煩了,因為此前的TCP連接已經釋放,根本找不到客戶端在哪。

為了能及時從服務器獲取數據,程序員們煞費苦心研究出來的各種解決方案其實都是在HTTP框架下做的妥協,沒法子,瀏覽器這東西只支持HTTP,我們有什么辦法。所以大家要么定時去輪詢,要么就靠長連接——客戶端發起請求,服務端把這個連接攥在手里不回復,等有消息了再回,如果超時了客戶端就再請求一次——其實大家也懂,這只是個減少了請求次數、實時性更好的輪詢,本質沒變。

WebSocket就是從技術根本上解決這個問題的:看名字就知道,它借用了Web的端口和消息頭來創建連接,后續的數據傳輸又和基于TCP的Socket幾乎完全一樣,但封裝了好多原本在Socket開發時需要我們手動去做的功能。比如原生支持wss安全訪問(跟https共用端口和證書)、創建連接時的校驗、從數據幀中自動拆分消息包等等。

換句話說,原本我們在瀏覽器里只能使用HTTP協議,現在有了Socket,還是個更好用的Socket。

了解了WebSocket的背景和特性之后,就可以回答它能不能取代AJAX這個問題了:

對于服務器與客戶端的雙向通信,WebSocket簡直是不二之選。如果不是還有少數舊版瀏覽器尚在服役的話,所有的輪詢、長連接等方式早就該廢棄掉。那些整合多種雙向推送消息方式的庫(如http://Socket.IO**、SignalR)當初最大的賣點就是兼容所有瀏覽器版本,自動識別舊版瀏覽器并采取不同的連接方式,現在也漸漸失去了優勢——所有新版瀏覽器都兼容WebSocket,直接用原生的就行了。說句題外話,這點很像jQuery,在原生js難用時迅速崛起,當其他庫和原生js都吸收了它的很多優勢時,慢慢就不那么重要了。

但是,很大一部分AJAX的使用場景仍然是傳統的請求-響應形式,比如獲取json數據、post表單之類。這些功能雖然靠WebSocket也能實現,但就像在原本傳輸數據流的TCP之上定義了基于請求的HTTP協議一樣,我們也要在WebSocket之上重新定義一種新的協議,最少也要加個request id用來區分每次響應數據對應的請求吧。……但是,何苦一層疊一層地造個新輪子呢?直接使用AJAX不是更簡單、更成熟嗎?

另外還有一種情況,也就是傳輸大文件、圖片、媒體流的時候,最好還是老老實實用HTTP來傳。如果一定要用WebSocket的話,至少也專門為這些數據專門開辟個新通道,而別去占用那條用于推送消息、對實時性要求很強的連接。否則會把串行的WebSocket徹底堵死的。

所以說,WebSocket在用于雙向傳輸、推送消息方面能夠做到靈活、簡便、高效,但在普通的Request-Response過程中并沒有太大用武之地,比起普通的HTTP請求來反倒麻煩了許多,甚至更為低效。每項技術都有自身的優缺點,在適合它的地方能發揮出最大長處,而看到它的幾個優點就不分場合地全方位推廣的話,可能會適得其反。

四、使用實例可以參考flv.js中的websocket-loader.js
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容