一、閱前熱身
什麼是keep-alive
1、keep-alive只是客戶端的一種建議
我們開啟百度首頁,進一步檢視header。
如圖,我們看到請求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、握手
①客戶端向服務端發起連線請求
如圖,我們在請求伺服器的時候,傳送了這樣的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協議狀態碼是101.
101表示協議切換成功。
我們檢視websocket的response header。如圖:
下面解釋下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 是什麼原理?為什麼可以實現持久連線?
更多精彩,請關注公眾號“聊聊程式碼”,讓我們一起聊聊“左手程式碼右手詩”的事兒。