websocket 歷史及使用詳解

1、閱前熱身

什麼是keep-alive

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

咱們打開百度首頁,進一步查看header。javascript

image_1b2idfp2k4ecu8pagh1mkutf39.png-415.7kB

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

Connection:keep-alive複製代碼

keep-alive是通知服務器,在這個HTTP Request/Responset結束後,不要當即斷開TCP鏈接(注意是TCP鏈接,和HTTP沒有關係),後面的HTTP Request仍然能夠經過這個TCP鏈接繼續傳送。java

可是!這只是個建議,服務器可能不支持,也可能忽略掉這個建議。也可能由於時間過久而直接斷開TCP鏈接nginx

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

因此,keep-alive只是客戶端建議的一種複用TCP鏈接的方式,至於服務器支持不支持,就由不得客戶端了。ajax

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

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

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

2、服務器的消息如何發給客戶端

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

①:什麼是ajax輪詢?

ajax輪詢的原理很是簡單,讓瀏覽器隔個幾秒就發送一次請求,詢問服務器是否有新信息。websocket

場景再現:

客戶端:啦啦啦,有沒有新信息(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技術雖然都能實現服務端消息的實時通知,可是各有缺點,都不是根本的解決辦法。
計算機界急需一種新的技術去處理這些需求~

3、websocket來啦

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

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

注:什麼是單工、半雙工、全工通訊?
信息只能單向傳送爲單工;
信息能雙向傳送但不能同時雙向傳送稱爲半雙工;
信息可以同時雙向傳送則稱爲全雙工。

websocket協議解析

wensocket協議包含兩部分:一部分是「握手」,一部分是「數據傳輸」。
爲了便於演示,咱們採用swoole創建一個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是否正確來判斷是否創建鏈接。

②:服務端返回握手應答

image_1b2ih7ard1oet1kangfig2uo01g.png-14.7kB

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

101表示協議切換成功。


咱們查看websocket的response header。如圖:

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握手成功!下面就盡情的傳輸數據吧!

二、數據傳輸

數據傳輸須要客戶端,沒什麼好說的了。

  • Chrome/Firefox/高版本IE/Safari等瀏覽器內置了JS語言的WebSocket客戶端
  • 能夠使用一些擴展來實現websocket客戶端。如php的swoole、workerman。

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

4、參考文章

Websocket協議之握手鍊接
WebSocket 是什麼原理?爲何能夠實現持久鏈接?

更多精彩,請關注公衆號「聊聊代碼」,讓咱們一塊兒聊聊「左手代碼右手詩」的事兒。

相關文章
相關標籤/搜索