WebSocket 是什麼?爲什麼能持久連接?

一、WebSocket 是什麼

WebSocket,是一種網絡傳輸協議,位於 OSI 模型的應用層。可在單個 TCP 連接上進行全雙工通信,能更好的節省服務器資源和帶寬並達到實時通迅 客戶端和服務器只需要完成一次握手,兩者之間就可以創建持久性的連接,並進行雙向數據傳輸

二、特點

全雙工 通信允許數據在兩個方向上同時傳輸,它在能力上相當於兩個單工通信方式的結合 例如指 A→B 的同時 B→A ,是瞬時同步的 二進制幀 採用了二進制幀結構,語法、語義與 HTTP 完全不兼容,相比 http/2,WebSocket 更側重於 “實時通信”,而 HTTP/2 更側重於提高傳輸效率,所以兩者的幀結構也有很大的區別 不像 HTTP/2 那樣定義流,也就不存在多路複用、優先級等特性 自身就是全雙工,也不需要服務器推送 協議名 引入 ws 和 wss 分別代表明文和密文的 websocket 協議,且默認端口使用 80 或 443,幾乎與 http 一致

ws://www.chrono.com
ws://www.chrono.com:8080/srv
ws://www.chrono.com:445/im?user=user_id=xxxx

握手 WebSocket 也要有一個握手過程,然後才能正式收發數據 客戶端發送數據格式如下:

GET /chat HTTP/1.1  Host: server.example.com Upgrade: websocket Connection:  Upgrade  Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==  Origin: http://example.com Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version:  13

服務端返回的數據格式: 

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=Sec-WebSocket-Protocol: chat

HTTP/1.1 101 Switching Protocols:表示服務端接受 WebSocket 協議的客戶端連接

優點

HTTP 協議的 “缺陷”

瞭解 http 的人都知道,HTTP 協議有一個缺陷:通信只能由客戶端發起。例如,我們想了解今天的天氣,只能是客戶端向服務器發出請求,服務器返回查詢結果。HTTP 協議做不到服務器主動向客戶端推送信息的, 這種單向請求的特點,註定瞭如果服務器有連續的狀態變化,客戶端要獲知就非常麻煩,客戶端只能使用” 輪詢” 的方式,即每隔一段時間,就發出一個請求,請求服務器有沒有狀態變化 。可見輪詢的效率低,非常浪費資源。

在 http1.1 中,默認開啓了一個叫 Keep-alive 的參數,官方的說法是可以用這個來作爲長連接。你是否以爲既然客戶端與服務器保持了長連接,服務器就能主動給客戶端推送消息呢?

關於 Keep-alive 的缺點

Keep-alive 的確可以實現長連接,但是這個長連接是有問題的,本質上依然是客戶端主動發起 - 服務端應答的模式,是沒法做到服務端主動發送通知給客戶端的。也就是說,在一個 HTTP 連接中,客戶端可以發送多個 Request,接收多個 Response。但是請記住 Request = Response , 在 HTTP 中永遠是這樣,一個 request 只能有一個 response。而且這個 response 也是被動的,不能主動發起。放上一張圖,圖左爲沒開啓 Keep-alive,圖右爲開啓了 Keep-alive,可以看出依然是一問一答的模式,向較左邊只是省略了每次的關閉和打開操作。

需要注意的是 Keep-alive 是指不需要多次建立連接,而非 http2.0 裏面的多路複用,多路複用的意思是客戶端可以同時向服務器端發送多個請求,服務器端也可以同時響應多個 Response.

關於 websocket

那麼如果我們需要服務器狀態變化的時候能夠主動通知客戶端,我們有沒有什麼辦法呢?這就要用到 websocket。

上圖對比可以看出,相對於傳統 HTTP 每次請求 - 應答都需要客戶端與服務端建立連接的模式,WebSocket 是類似 Socket 的 TCP 長連接的通訊模式,一旦 WebSocket 連接建立後,後續數據都以幀序列的形式傳輸。在客戶端斷開 WebSocket 連接或 Server 端斷掉連接前,不需要客戶端和服務端重新發起連接請求。在海量併發及客戶端與服務器交互負載流量大的情況下,極大的節省了網絡帶寬資源的消耗,有明顯的性能優勢,且客戶端發送和接受消息是在同一個持久連接上發起,實時性優勢明顯。

WebSocket API 是 HTML5 標準的一部分, 但這並不代表 WebSocket 一定要用在 HTML 中,或者只能在基於瀏覽器的應用程序中使用。

在 WebSocket 中,只需要服務器和瀏覽器通過 TCP 協議進行一個握手的動作,然後單獨建立一條 TCP 的通信通道進行數據的傳送。WebSocket 同 HTTP 一樣也是應用層的協議,但是它是一種雙向通信協議,是建立在 TCP 之上的。websocket 的流程大概是以下幾步:

1、瀏覽器、服務器建立 TCP 連接,三次握手。這是通信的基礎,傳輸控制層,若失敗後續都不執行。2、TCP 連接成功後,瀏覽器通過 HTTP 協議向服務器傳送 WebSocket 支持的版本號等信息。(開始前的 HTTP 握手) 3、服務器收到客戶端的握手請求後,同樣採用 HTTP 協議回饋數據。4、當收到了連接成功的消息後,通過 TCP 通道進行傳輸通信。

也就是說 WebSocket 在建立握手時,數據是通過 HTTP 傳輸的。但是建立之後,在真正傳輸時候是不需要 TCP 協議的。

看看一次 websocket 的握手請求與應答的報文

WebSocket 客戶端連接報文

GET /webfin/websocket/ HTTP/1.1  Host: localhost Upgrade: websocket Connection:  Upgrade  Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==  Origin: http://localhost :8080  Sec-WebSocket-Version:  13

可以看到,客戶端發起的 WebSocket 連接報文類似傳統 HTTP 報文,”Upgrade:websocket”參數值表明這是 WebSocket 類型請求,“Sec-WebSocket-Key”是 WebSocket 客戶端發送的一個 base64 編碼的密文,要求服務端必須返回一個對應加密的 “Sec-WebSocket-Accept” 應答,否則客戶端會拋出 “Error during WebSocket handshake” 錯誤,並關閉連接。

服務端收到報文後返回的數據格式類似:

WebSocket 服務端響應報文

GET /webfin/websocket/ HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==
Origin: 
http://localhost
:8080
Sec-WebSocket-Version: 13

“Sec-WebSocket-Accept” 的值是服務端採用與客戶端一致的密鑰計算出來後返回客戶端的,“HTTP/1.1 101 Switching Protocols” 表示服務端接受 WebSocket 協議的客戶端連接,經過這樣的請求 - 響應處理後,客戶端服務端的 WebSocket 連接握手成功, 後續就可以進行 TCP 通訊了。

WebSocket 與 Socket 的關係

Socket 其實並不是一個協議,而是爲了方便使用 TCP 或 UDP 而抽象出來的一層,是位於應用層和傳輸控制層之間的一組接口。

Socket 是應用層與 TCP/IP 協議族通信的中間軟件抽象層,它是一組接口。在設計模式中,Socket 其實就是一個門面模式,它把複雜的 TCP/IP 協議族隱藏在 Socket 接口後面,對用戶來說,一組簡單的接口就是全部,讓 Socket 去組織數據,以符合指定的協議。

當兩臺主機通信時,必須通過 Socket 連接,Socket 則利用 TCP/IP 協議建立 TCP 連接。TCP 連接則更依靠於底層的 IP 協議,IP 協議的連接則依賴於鏈路層等更低層次。

WebSocket 則是一個典型的應用層協議。

WebSocket 與 HTTP

WebSocket 協議在 2008 年誕生,2011 年成爲國際標準。現在所有瀏覽器都已經支持了。WebSocket 的最大特點就是,服務器可以主動向客戶端推送信息,客戶端也可以主動向服務器發送信息,是真正的雙向平等對話。

HTTP 有 1.1 和 1.0 之說,也就是所謂的 keep-alive ,把多個 HTTP 請求合併爲一個,但是 Websocket 其實是一個新協議,跟 HTTP 協議基本沒有關係,只是爲了兼容現有瀏覽器,所以在握手階段使用了 HTTP 。

下面一張圖說明了 HTTP 與 WebSocket 的主要區別:

WebSocket 的其他特點:

WebSocket 原理及如何實現長連接

websocket 相當於 HTTP 的一個補充協議,通過 http request 建立連接,不需要再發送 request,之後保持一端與另外一端的 TCP 連接。

在實際應用中,一個 socket 與另外一端的連接可能會經過千山萬水(多個路由、多箇中間服務器),中間有各種轉發、過濾。

所以後來更新了,添加了 Ping/Pong Frame(RFC 6455 - The WebSocket Protocol),可以說這是一個特殊的數據包,

這個數據包只有簡單的一些的元數據,不涉及數據傳輸。維持連接的活躍性與持久性。

參考文獻

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/1ZdDvHSntrLuLQgdCZxqcw