websocket 歷史及使用詳解

子路發表於2017-03-31

一、閱前熱身

什麼是keep-alive

1、keep-alive只是客戶端的一種建議

我們開啟百度首頁,進一步檢視header。

websocket 歷史及使用詳解
image_1b2idfp2k4ecu8pagh1mkutf39.png-415.7kB

如圖,我們看到請求header中有一行:

Connection:keep-alive複製程式碼

keep-alive是通知伺服器,在這個HTTP Request/Responset結束後,不要立即斷開TCP連線(注意是TCP連線,和HTTP沒有關係),後面的HTTP Request仍然可以通過這個TCP連線繼續傳送。

但是!這只是個建議,伺服器可能不支援,也可能忽略掉這個建議。也可能因為時間太久而直接斷開TCP連線

通俗點解釋就是:keep-alive只是通知伺服器,您先別掛,一會兒可能還有活兒,至於它掛不掛還是看它心情。

所以,keep-alive只是客戶端建議的一種複用TCP連線的方式,至於伺服器支援不支援,就由不得客戶端了。

2、keep-alive只是http協議中的一部分

keep-alive是http協議中的一部分,也即客戶端可以主動的發起request到伺服器,伺服器只能被動的response給客戶端。

我要想實現伺服器主動的push訊息給客戶端,keep-alive是無能無力的。

二、伺服器的訊息如何發給客戶端

long long ago~ 伺服器端要想主動的push訊息給客戶端(比如網頁聊天室訊息的即時收發),這是不可能滴。
但是,我可以使用ajax輪詢、long poll 技術造一個服務端給客戶端主動push訊息的假象。

①:什麼是ajax輪詢?

ajax輪詢的原理非常簡單,讓瀏覽器隔個幾秒就傳送一次請求,詢問伺服器是否有新資訊。

場景再現:

客戶端:啦啦啦,有沒有新資訊(Request)
服務端:沒有(Response)
客戶端:啦啦啦,有沒有新資訊(Request)
服務端:沒有。。(Response)
客戶端:啦啦啦,有沒有新資訊(Request)
服務端:你好煩啊,沒有啊。。(Response)
客戶端:啦啦啦,有沒有新訊息(Request)
服務端:好啦好啦,有啦給你。(Response)
客戶端:啦啦啦,有沒有新訊息(Request)
服務端:。。。。。沒。。。。沒。。。沒有(Response) ---- loop複製程式碼

但是這樣,有沒有發現,大大增加了服務端的負載,並且速度還慢。

②:什麼是long poll?

long poll和ajax差不多,原理都是採用輪詢的方式。只不過long poll是採取的阻塞的方式去輪詢。
也即客戶端發起一個請求連線,這個連線會阻塞住,直到服務端有了訊息,才會response給客戶端。

注:阻塞、非阻塞的理解,請參考我之前的文章:nginx、swoole高併發原理初探

場景再現:

客戶端:啦啦啦,有沒有新資訊,沒有的話就等有了才返回給我吧(Request)
服務端:額。。 等待到有訊息的時候。。來 給你(Response)
客戶端:啦啦啦,有沒有新資訊,沒有的話就等有了才返回給我吧(Request) -loop複製程式碼

long pull 雖然降低了伺服器的負載,但是需要伺服器有很高的併發能力才可以。
而目前處理高併發的模型基本都是非同步非阻塞的模型(比如nginx)。

既想阻塞,又想高併發,幾乎不可能。

③:總結

ajax輪詢、long poll技術雖然都能實現服務端訊息的實時通知,但是各有缺點,都不是根本的解決辦法。
計算機界急需一種新的技術去處理這些需求~

三、websocket來啦

既然ajax輪詢、long poll都不怎麼樣。我們發明一種新的協議吧!

Websocket協議解決了伺服器與客戶端全雙工通訊的問題。

注:什麼是單工、半雙工、全工通訊?
資訊只能單向傳送為單工;
資訊能雙向傳送但不能同時雙向傳送稱為半雙工;
資訊能夠同時雙向傳送則稱為全雙工。

websocket協議解析

wensocket協議包含兩部分:一部分是“握手”,一部分是“資料傳輸”。
為了便於演示,我們採用swoole建立一個websocket伺服器來演示。

1、握手

①客戶端向服務端發起連線請求

websocket 歷史及使用詳解
image_1b2igg66d159v128qt59v2l48cm.png-59.3kB

如圖,我們在請求伺服器的時候,傳送了這樣的request header。

下面我們就一些比較重要的欄位資訊進行說明:

Connection:Upgrade #通知伺服器協議升級
Upgrade:websocket  #協議升級為websocket協議
Host:0.0.0.0:9501  #升級協議的服務主機:埠地址
Sec-WebSocket-Key:K8o1cNIxO2pR6inTIDBSgg== #傳輸給伺服器的key
Sec-WebSocket-Version:13 #websocket協議版本13複製程式碼

Sec-WebSocket-Key有什麼用呢?
客戶端將這個key傳送給伺服器,伺服器將這個key進行處理,將處理後的key返回給客戶端,客戶端根據這個key是否正確來判斷是否建立連線。

②:服務端返回握手應答

websocket 歷史及使用詳解
image_1b2ih7ard1oet1kangfig2uo01g.png-14.7kB

如圖,我們看到websocket協議狀態碼是101.

101表示協議切換成功。


我們檢視websocket的response header。如圖:

websocket 歷史及使用詳解
image_1b2ih030qjdc1dllmshto0eph13.png-29.6kB

下面解釋下reponse header欄位的含義

Connection:Upgrade #協議升級成功
Sec-WebSocket-Accept:GnoYH/ip/ZMh+a5rX5P/YR6e68g= #服務端處理之後的key
Sec-WebSocket-Version:13#websocket 協議版本號
Upgrade:websocket#協議升級為websocket複製程式碼

至此,websocket握手成功!下面就盡情的傳輸資料吧!

2、資料傳輸

資料傳輸需要客戶端,沒什麼好說的了。

  • Chrome/Firefox/高版本IE/Safari等瀏覽器內建了JS語言的WebSocket客戶端
  • 可以使用一些擴充套件來實現websocket客戶端。如php的swoole、workerman。

    注意:非WebSocket客戶端不能與WebSocket伺服器通訊

四、參考文章

Websocket協議之握手連線
WebSocket 是什麼原理?為什麼可以實現持久連線?

更多精彩,請關注公眾號“聊聊程式碼”,讓我們一起聊聊“左手程式碼右手詩”的事兒。

websocket 歷史及使用詳解

相關文章