不得不了解的webSocket

WebSocket是一種網絡通信協議。

為什么需要 WebSocket?

因為HTTP 協議有一個缺陷:通信只能由客戶端發起。這種單向請求的特點,注定了如果服務器有連續的狀態變化,客戶端要獲知就非常麻煩。我們只能使用"輪詢":每隔一段時候,就發出一個詢問,了解服務器有沒有新的信息。

輪詢技術有:(短)輪詢(Polling),Comet的長輪詢(Long-polling)和流技術(Http Streaming)等。

輪詢的效率低,非常浪費資源。所以websocket就應用而生了。

W3C 在 HTML5中提供了一種clientserver 間進行全雙工通訊的網絡技術WebSocketWebSocket是一個全新的、獨立的協議,基于 TCP 協議,與HTTP 協議兼容卻不會融入HTTP協議,僅僅作為 HTML5 的一部分。

WebSocket原理

WebSocket是一種協議,是一種與HTTP 同等的網絡協議,兩者都是應用層協議,都基于 TCP 協議。但是 WebSocket 是一種雙向通信協議,在建立連接之后,WebSocketserverclient 都能主動向對方發送或接收數據。同時,WebSocket在建立連接時需要借助 HTTP 協議,連接建立好了之后 clientserver 之間的雙向通信就與 HTTP 無關了。

相比于傳統HTTP 的每次“請求-應答”都要client 與 server 建立連接的模式,WebSocket 是一種長連接的模式。就是一旦WebSocket 連接建立后,除非client 或者 server 中有一端主動斷開連接,否則每次數據傳輸之前都不需要HTTP 那樣請求數據。

接下來,從報文層面談一下WebSocketHTTP 的差異

首先,client 發起WebSocket連接,報文類似于 HTTP,但主要有幾點不一樣的地方:

  • Upgrade: websocket: 表明這是一個 WebSocket 類型請求,意在告訴server 需要將通信協議切換到WebSocket

  • Sec-WebSocket-Key: 是 client發送的一個 base64 編碼的密文,要求server必須返回一個對應加密的 Sec-WebSocket-Accept 應答,否則client 會拋出 Error during WebSocket handshake錯誤,并關閉連接。

server 收到報文后,如果支持WebSocket 協議,那么就會將自己的通信協議切換到WebSocket,返回以下信息:

  • HTTP/1.1 101 WebSocket Protocol Handshake:返回的狀態碼為 101,表示同意 client的協議轉換請求。
  • Upgrade: websocket
  • Connection: Upgrade
  • Sec-WebSocket-Accept:
    ...

以上都是利用HTTP協議完成的。這樣,經過“請求-相應”的過程, serverclientWebSocket 連接握手成功,后續便可以進行TCP通訊了,也就沒有HTTP 什么事了。

WebSocket通信特點

  • 最大特點就是,服務器可以主動向客戶端推送信息,客戶端也可以主動向服務器發送信息,是真正的雙向平等對話,屬于服務器推送技術的一種。

  • 建立在TCP 協議之上,服務器端的實現比較容易。

  • HTTP協議有著良好的兼容性。默認端口也是80443,并且握手階段采用HTTP 協議,因此握手時不容易屏蔽,能通過各種 HTTP 代理服務器。

  • 數據格式比較輕量,性能開銷小,通信高效。

  • 可以發送文本,也可以發送二進制數據。

  • 沒有同源限制,客戶端可以與任意服務器通信。

  • 協議標識符是ws(如果加密,則為wss),服務器網址就是 URL

WebSocket實例

客戶端實例

var ws = new WebSocket("(wss://echo.websocket.org/)");

ws.onopen = function(evt) {
  console.log("Connection open ..."); 
  ws.send("Hello WebSockets!");
};
 
ws.onmessage = function(evt) { 
  console.log( "Received Message: " + evt.data); 
  ws.close();
};

ws.onclose = function(evt) { 
  console.log("Connection closed.");
}; 

客戶端API

  • WebSocket 對象作為一個構造函數,用于新建 WebSocket 實例。
 var ws = new WebSocket('ws://localhost:8000');

執行上面語句之后,客戶端就會與服務器進行連接。

  • webSocket.readyState返回實例對象的當前狀態,值為:
    CONNECTING:值為0,表示正在連接。
    OPEN:值為1,表示連接成功,可以通信了。
    CLOSING:值為2,表示連接正在關閉。
    CLOSED:值為3,表示連接已經關閉,或者打開連接失敗。
  • webSocket.onopen用于指定連接成功后的回調函數,也可以使用addEventListener方法。
  • webSocket.onclose用于指定連接關閉后的回調函數。
  • webSocket.onmessage用于指定收到服務器數據后的回調函數,也可以使用addEventListener方法。
  • webSocket.send()用于向服務器發送數據。
  • webSocket.bufferedAmount表示還有多少字節的二進制數據沒有發送出去。它可以用來判斷發送是否結束。
  • webSocket.onerror用于指定報錯時的回調函數,也可以使用addEventListener方法。

WebSocket 服務器的實現可以使用node中的μWebSocketsSocket.IOWebSocket-Node

完整demo地址

參考資料:
WebSocket 與 Socket.IO
WebSocket 教程
HTML5 WebSocket教程

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,869評論 18 139
  • 國家電網公司企業標準(Q/GDW)- 面向對象的用電信息數據交換協議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 11,121評論 6 13
  • 01 像是一個走在獨立音樂長河岸邊的年輕人,他少年老成、深諳其道,大大方方,不慌不忙穿行于人潮之中,輕易地就找來了...
    伊伊烑閱讀 997評論 0 3
  • 每個人都帶著功課來到世間昨天跟幾個功課比較重的朋友修煉如果機緣合適再過兩年我們有機會共修所以聊的話題比較深從商業模...
    承謙閱讀 529評論 0 0
  • 做一個美麗但窮的年輕女孩是什么體驗? 女孩子窮是因為花錢的地方多,而且賺的錢不一定跟得上消費節奏...
    暉越閱讀 957評論 4 0