標籤:

深入剖析WebSocket的原理

前言

針對以上您提起的WebSocket的相關話題,給您做一下系統的梳理,WebSocket是和http類似的可以實現全雙工可持久連接通信的應用層協議,以下深入剖析一下WebSocket的原理。

什麼是WebSocket

首先,我們需要弄明白,WebSocket本質上一種計算機網路應用層的協議,用來彌補http協議在持久通信能力上的不足。

我們知道http協議本身是無狀態協議,每一個新的http請求,只能通過客戶端主動發起,通過 建立連接-->傳輸數據-->斷開連接 的方式來傳輸數據,傳送完連接就斷開了,也就是這次http請求已經完全結束了(雖然http1.1增加了keep-alive請求頭可以通過一條通道請求多次,但本質上還是一樣的)。

並且伺服器是不能主動給客戶端發送數據的(因為之前的請求得到響應後連接就斷開了,之後伺服器根本不知道誰請求過),客戶端也不會知道之前請求的任何信息。

所以說,http協議本身是沒有持久通信能力的,但是我們在實際的應用中,是很需要這種能力的,所以WebSocket協議由此而生,於2011年被IETF定為標準RFC6455,並被RFC7936所補充規範。

並且在HTML5標準中增加了有關WebSocket協議的相關api,所以只要實現了HTML5標準的客戶端,就可以與支持WebSocket協議的伺服器進行全雙工的持久通信了。

ps:這裡的持久通信能力指的是協議本身的能力,我們當然可以通過編程的方式實現這種功能,比如輪詢的方式,但誰不喜歡原生就支持呢?

ps2:計算機網路里還有socket關鍵字,這裡的socket指的是運輸層協議的某一端,泛指某個應用程序。

ps3: unix編程里還有一個socket介面,這裡的譯名是套接字,泛指應用層協議的埠號。

WebSocket協議的原理

與http協議一樣,WebSocket協議也需要通過已建立的TCP連接來傳輸數據。具體實現上是通過http協議建立通道,然後在此基礎上用真正的WebSocket協議進行通信,所以WebSocket協議和http協議是有一定的交叉關係的。

下面是WebSocket協議請求頭:

其中請求頭中重要的欄位:

Connection:UpgradeUpgrade:websocketSec-WebSocket-Extensions:permessage-deflate; client_max_window_bitsSec-WebSocket-Key:mg8LvEqrB2vLpyCNnCJV3Q==Sec-WebSocket-Version:13

1. Connection和Upgrade欄位告訴伺服器,客戶端發起的是WebSocket協議請求

2. Sec-WebSocket-Extensions表示客戶端想要表達的協議級的擴展

3. Sec-WebSocket-Key是一個Base64編碼值,由瀏覽器隨機生成

4. Sec-WebSocket-Version表明客戶端所使用的協議版本

而得到的響應頭中重要的欄位:

Connection:UpgradeUpgrade:websocketSec-WebSocket-Accept:AYtwtwampsFjE0lu3kFQrmOCzLQ=

1. Connection和Upgrade欄位與請求頭中的作用相同

2. Sec-WebSocket-Accept表明伺服器接受了客戶端的請求

Status Code:101 Switching Protocols

並且http請求完成後響應的狀態碼為101,表示切換了協議,說明WebSocket協議通過http協議來建立運輸層的TCP連接,之後便與http協議無關了。

WebSocket協議具體內容請參考:github.com/zhangkaitao/

WebSocket協議的優缺點

優點:

· WebSocket協議一旦建議後,互相溝通所消耗的請求頭是很小的

· 伺服器可以向客戶端推送消息了

缺點:

· 少部分瀏覽器不支持,瀏覽器支持的程度與方式有區別

WebSocket協議的應用場景

· 即時聊天通信

· 多玩家遊戲

· 在線協同編輯/編輯

· 實時數據流的拉取與推送

· 體育/遊戲實況

· 實時地圖位置

NodeJS的簡單實現

服務端

// 安裝ws模塊// npm install ws// 新建index.js文件// -----// 導入ws模塊const WebSocket = require(ws)// 新建一個WebSocketServerconst wss = new WebSocket.Server({ port: 3000 })// 伺服器監聽連接事件wss.on(connection, ws => {// 伺服器監聽消息事件 ws.on(message, msg => {console.log(伺服器收到:, msg) })// 伺服器向客戶端發送消息 ws.send(這是伺服器發送的信息)})

客戶端

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width_=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><script>// 這是瀏覽器原生支持的WebSocket API,在支持HTML5標準的瀏覽器上可以直接使用var ws = new WebSocket(ws://localhost:3000)// 當連接成功後就可以發送消息了 ws.onopen = function() {console.log(連接已建立) ws.send(這是客戶端發出的信息) }// 收到消息後做對應的處理 ws.onmessage = function(e) {console.log(e.data) }</script></body></html>

運行結果

伺服器端

瀏覽器端

希望能幫到大家。


推薦閱讀:

MQTT和Websocket的區別是什麼?
一步一步教您用websocket+nodeJS搭建簡易聊天室(4)
web AR系統-3 效率評估-websocket
tornado如何實現非同步websocket推送?

TAG:WebSocket | HTML5 |