http通訊只能一來一回,不能直接回包,因而出現了websocket實時通信web
在websocket沒有出現以前,總會有一些需求,須要獲取數據,可是這些數據殊不知道哪一個時間點才能獲取到,因而,你們使用了輪詢來解決服務器推送的問題。瀏覽器
HTTP協議只能從客戶端發出請求,服務器處理返回請求(這裏能夠看下圖),可是服務器不能主動給客戶端發送請求,因而解決服務器推送的問題,就只能靠輪詢了。服務器
輪詢分爲兩種websocket
短輪詢:定時發送http請求socket
長輪詢:發送請求直到收到消息or超時後繼續發送下一個請求加密
可是,輪詢並不能完美的解決服務器推送的問題spa
websocket的出現,就是爲了解決服務器推送的問題。3d
WebSocket是HTML5開始提供的一種在單個 TCP 鏈接上進行全雙工(通訊雙方既是接收方也是發送方,兩端設備能夠同時發送和接收數據)通信的協議。code
websocket的連接仍是比較簡單的,只要進行一次握手,就能夠進行後續的通信了,這裏分爲三步:cdn
在第一步的時候進行了握手,這裏來看一下請求的詳情
// 請求
GET / HTTP/1.1
Upgrade: websocket // 升級爲websocket協議
Connection: Upgrade
Host: localhost:3000 // 請求host
Origin: http://binnie.com // 請求來源
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ== // 用於後續計算accept
Sec-WebSocket-Version: 13 // websocket版本號
複製代碼
// 回包
HTTP/1.1 101 Switching Protocols // 101表示連接成功
Upgrade: websocket // 與請求對應
Connection: Upgrade
// 使用key計算得來,儘可能避免普通HTTP請求被誤認爲Websocket協議
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
複製代碼
WebSocket協議使用幀(Frame)收發數據
客戶端發送給服務端的幀必須經過4字節的掩碼(Masking-key)加密,服務端收到消息後,用掩碼對數據幀的Payload Data進行異或運算解碼獲得數據,若是服務端收到未經掩碼加密的數據幀,則應該立刻關閉該WebSocket。
服務端發給客戶端的數據則不須要掩碼加密,客戶端若是收到了服務端的掩碼加密的數據,則也必須關閉它。
上圖爲websocket的幀格式,下面咱們一個個來分析
這裏從左往右看,橫向爲32位(bit)
因此,websocket傳遞數據時最小的請求頭爲 FIN+RSV1-3+opcode+MASK+Payload len+Masking-key = 6 byte(字節),剩下的就都是實際數據,相比於http頭部小得多。
websocket是很好的實時雙向通信,不過兼容性只到ie10,因此不支持websocket的瀏覽器就只能使用輪詢等方法來兼容。
因爲低版本瀏覽器不支持websocket,須要使用輪詢來兼容,因而出現了不少websocket庫,後面再分析websocket庫的實現。