WebSocket 是 HTML5 一種新的協定。它實作了浏覽器與伺服器全雙工通信,能更好的節省伺服器資源和帶寬并達到實時通訊,它建立在 TCP 之上,同 HTTP 一樣通過 TCP 來傳輸資料,但是它和 HTTP 最大不同是:
- WebSocket 是一種雙向通信協定,在建立連接配接後,WebSocket 伺服器和 Browser/Client Agent 都能主動的向對方發送或接收資料,就像 Socket 一樣;
- WebSocket 需要類似 TCP 的用戶端和伺服器端通過握手連接配接,連接配接成功後才能互相通信。
Websocket是一種在單個TCP連接配接上進行全雙工通訊的協定,在Websocket協定中,用戶端和服務端隻需要做一個握手的動作,就能形成一條通道,兩者之間可以進行資料互相傳送。
是以WebSocket協定分為兩部分:
- 握手
- 資料傳輸
用戶端發送一個請求
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com
Origin: null
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13
可以看到,用戶端發起的 WebSocket 連接配接封包類似傳統 HTTP 封包,”Upgrade:websocket”參數值表明這是 WebSocket 類型請求,“Sec-WebSocket-Key”是 WebSocket 用戶端發送的一個 base64 編碼的密文,要求服務端必須傳回一個對應加密的“Sec-WebSocket-Accept”應答,否則用戶端會抛出“Error during WebSocket handshake”錯誤,并關閉連接配接。
服務端收到封包後傳回的資料格式類似:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
Sec-WebSocket-Origin: null
Sec-WebSocket-Location: ws://example.com/
收到這一段響應後,用戶端需要比對Sec-WebSocket-Accept值,這個值表示伺服器同意握手建立連接配接,是用戶端傳輸過來的Sec-WebSocket-Key跟“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”拼接後,用SHA-1加密,并進行BASE-64編碼得來的。
用戶端收到Sec-WebSocket-Accept後,将本地的Sec-WebSocket-Key進行同樣的編碼,然後比對。
隻需要經過一次HTTP請求,就可以做到源源不斷的資訊傳送了。(在程式設計中,這種設計叫做回調,即:你有資訊了再來通知我,而不是我傻乎乎的每次跑來問你)
這樣的協定解決了上面同步有延遲,而且還非常消耗資源的這種情況。
在傳統的方式上,要不斷的建立,關閉HTTP協定,由于HTTP是非狀态性的,每次都要重新傳輸identity info(鑒别資訊),來告訴服務端你是誰。
但是Websocket隻需要一次HTTP握手,是以說整個通訊過程是建立在一次連接配接/狀态中,也就避免了HTTP的非狀态性,服務端會一直知道你的資訊,直到你關閉請求,這樣就解決了接線員要反複解析HTTP協定,還要檢視identity info的資訊。
HTTP協定的另外一個特點,被動性。
何為被動性呢,其實就是,服務端不能主動聯系用戶端,隻能有用戶端發起。
同時由客戶主動詢問,轉換為伺服器(推送)有資訊的時候就發送(當然用戶端還是等主動發送資訊過來的。。),沒有資訊的時候就交給接線員(Nginx),不需要占用本身速度就慢的客服(Handler)了
--------------------
至于怎麼在不支援Websocket的用戶端上使用Websocket。。答案是:不能
但是可以通過上面說的 long poll 和 ajax 輪詢來 模拟出類似的效果
-----