咱們打開百度首頁,進一步查看header。javascript
如圖,咱們看到請求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協議中的一部分,也即客戶端能夠主動的發起request到服務器,服務器只能被動的response給客戶端。segmentfault
我要想實現服務器主動的push消息給客戶端,keep-alive是無能無力的。瀏覽器
long long ago~ 服務器端要想主動的push消息給客戶端(好比網頁聊天室消息的即時收發),這是不可能滴。
可是,我能夠使用ajax輪詢、long poll 技術造一個服務端給客戶端主動push消息的假象。服務器
ajax輪詢的原理很是簡單,讓瀏覽器隔個幾秒就發送一次請求,詢問服務器是否有新信息。websocket
場景再現:
客戶端:啦啦啦,有沒有新信息(Request)
服務端:沒有(Response)
客戶端:啦啦啦,有沒有新信息(Request)
服務端:沒有。。(Response)
客戶端:啦啦啦,有沒有新信息(Request)
服務端:你好煩啊,沒有啊。。(Response)
客戶端:啦啦啦,有沒有新消息(Request)
服務端:好啦好啦,有啦給你。(Response)
客戶端:啦啦啦,有沒有新消息(Request)
服務端:。。。。。沒。。。。沒。。。沒有(Response) ---- loop複製代碼
可是這樣,有沒有發現,大大增長了服務端的負載,而且速度還慢。
long poll和ajax差很少,原理都是採用輪詢的方式。只不過long poll是採起的阻塞的方式去輪詢。
也即客戶端發起一個請求鏈接,這個鏈接會阻塞住,直到服務端有了消息,纔會response給客戶端。
注:阻塞、非阻塞的理解,請參考我以前的文章:nginx、swoole高併發原理初探
場景再現:
客戶端:啦啦啦,有沒有新信息,沒有的話就等有了才返回給我吧(Request)
服務端:額。。 等待到有消息的時候。。來 給你(Response)
客戶端:啦啦啦,有沒有新信息,沒有的話就等有了才返回給我吧(Request) -loop複製代碼
long pull 雖然下降了服務器的負載,可是須要服務器有很高的併發能力才能夠。
而目前處理高併發的模型基本都是異步非阻塞的模型(好比nginx)。
既想阻塞,又想高併發,幾乎不可能。
ajax輪詢、long poll技術雖然都能實現服務端消息的實時通知,可是各有缺點,都不是根本的解決辦法。
計算機界急需一種新的技術去處理這些需求~
既然ajax輪詢、long poll都不怎麼樣。咱們發明一種新的協議吧!
Websocket協議解決了服務器與客戶端全雙工通訊的問題。
注:什麼是單工、半雙工、全工通訊?
信息只能單向傳送爲單工;
信息能雙向傳送但不能同時雙向傳送稱爲半雙工;
信息可以同時雙向傳送則稱爲全雙工。
wensocket協議包含兩部分:一部分是「握手」,一部分是「數據傳輸」。
爲了便於演示,咱們採用swoole創建一個websocket服務器來演示。
①客戶端向服務端發起鏈接請求
如圖,咱們在請求服務器的時候,發送了這樣的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是否正確來判斷是否創建鏈接。
②:服務端返回握手應答
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握手成功!下面就盡情的傳輸數據吧!
數據傳輸須要客戶端,沒什麼好說的了。
注意:非WebSocket客戶端不能與WebSocket服務器通訊
Websocket協議之握手鍊接
WebSocket 是什麼原理?爲何能夠實現持久鏈接?
更多精彩,請關注公衆號「聊聊代碼」,讓咱們一塊兒聊聊「左手代碼右手詩」的事兒。