Websocket - 學習/實踐

1.應用場景

主要用於在瀏覽器和服務器之間建立一個不受限的雙向通信的通道,比如說,服務器可以在任意時刻發送消息給瀏覽器。

2.學習/操作

1.介紹

WebSocket是HTML5新增的協議,它的目的是在瀏覽器和服務器之間建立一個不受限的雙向通信的通道,比如說,服務器可以在任意時刻發送消息給瀏覽器。

 

出現歷史原因:

爲什麼傳統的HTTP協議不能做到WebSocket實現的功能?這是因爲HTTP協議是一個請求-響應協議,請求必須先由瀏覽器發給服務器,服務器才能響應這個請求,再把數據發送給瀏覽器。換句話說,瀏覽器不主動請求,服務器是沒法主動發數據給瀏覽器的。

這樣一來,要在瀏覽器中搞一個實時聊天,在線炒股(不鼓勵),或者在線多人遊戲的話就沒法實現了,只能藉助Flash這些插件。

也有人說,HTTP協議其實也能實現啊,比如用輪詢或者Comet。輪詢是指瀏覽器通過JavaScript啓動一個定時器,然後以固定的間隔給服務器發請求,詢問服務器有沒有新消息。這個機制的缺點一是實時性不夠,二是頻繁的請求會給服務器帶來極大的壓力。

Comet本質上也是輪詢,但是在沒有消息的情況下,服務器先拖一段時間,等到有消息了再回復。這個機制暫時地解決了實時性問題,但是它帶來了新的問題:以多線程模式運行的服務器會讓大部分線程大部分時間都處於掛起狀態,極大地浪費服務器資源。另外,一個HTTP連接在長時間沒有數據傳輸的情況下,鏈路上的任何一個網關都可能關閉這個連接,而網關是我們不可控的,這就要求Comet連接必須定期發一些ping數據表示連接“正常工作”。

以上兩種機制都治標不治本,所以,HTML5推出了WebSocket標準,讓瀏覽器和服務器之間可以建立無限制的全雙工通信,任何一方都可以主動發消息給對方。

 

WebSocket協議

WebSocket並不是全新的協議,而是利用了HTTP協議來建立連接。我們來看看WebSocket連接是如何創建的。

首先,WebSocket連接必須由瀏覽器發起,因爲請求協議是一個標準的HTTP請求,格式如下:

GET ws://localhost:3000/ws/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Origin: http://localhost:3000
Sec-WebSocket-Key: client-random-string
Sec-WebSocket-Version: 13

該請求和普通的HTTP請求有幾點不同:

  1. GET請求的地址不是類似/path/,而是以ws://開頭的地址;
  2. 請求頭Upgrade: websocketConnection: Upgrade表示這個連接將要被轉換爲WebSocket連接;
  3. Sec-WebSocket-Key是用於標識這個連接,並非用於加密數據;
  4. Sec-WebSocket-Version指定了WebSocket的協議版本。

隨後,服務器如果接受該請求,就會返回如下響應:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: server-random-string

該響應代碼101表示本次連接的HTTP協議即將被更改,更改後的協議就是Upgrade: websocket指定的WebSocket協議。

版本號和子協議規定了雙方能理解的數據格式,以及是否支持壓縮等等。如果僅使用WebSocket的API,就不需要關心這些。

 

現在,一個WebSocket連接就建立成功,瀏覽器和服務器就可以隨時主動發送消息給對方。

消息有兩種,一種是文本,一種是二進制數據。通常,我們可以發送JSON格式的文本,這樣,在瀏覽器處理起來就十分容易。

 

爲什麼WebSocket連接可以實現全雙工通信而HTTP連接不行呢?實際上HTTP協議是建立在TCP協議之上的,TCP協議本身就實現了全雙工通信,但是HTTP協議的請求-應答機制限制了全雙工通信。WebSocket連接建立以後,其實只是簡單規定了一下:接下來,咱們通信就不使用HTTP協議了,直接互相發數據吧。

 

安全的WebSocket連接機制和HTTPS類似。

首先,瀏覽器用wss://xxx創建WebSocket連接時,會先通過HTTPS創建安全的連接,然後,該HTTPS連接升級爲WebSocket連接,底層通信走的仍然是安全的SSL/TLS協議。

 

 

2.實現

瀏覽器

很顯然,要支持WebSocket通信,瀏覽器得支持這個協議,這樣才能發出ws://xxx的請求。目前,支持WebSocket的主流瀏覽器如下:

Chrome

Firefox

IE >= 10

Sarafi >= 6

Android >= 4.4

iOS >= 8

服務器

由於WebSocket是一個協議,服務器具體怎麼實現,取決於所用編程語言和框架本身。Node.js本身支持的協議包括TCP協議和HTTP協議,要支持WebSocket協議,需要對Node.js提供的HTTPServer做額外的開發。已經有若干基於Node.js的穩定可靠的WebSocket實現,我們直接用npm安裝使用即可。

 

 

3.個人實踐

後端語言: nodeJS/PHP 各實現一個

 

nodeJS

聊天室:https://github.com/ningxiaofa/talking-room   //有些庫已經被摒棄,後面修復

效果如下:

分別開不同瀏覽器窗口【或者chrome的無痕窗口】,輸入local host:3000 回車即可

 

 

 

後續補充

...

3.問題/補充

TBD

4.參考

https://www.liaoxuefeng.com/wiki/1022910821149312/1103303693824096  //廖雪峯 - websocket

https://www.liaoxuefeng.com/wiki/1022910821149312/1103327377678688

https://www.liaoxuefeng.com/wiki/1022910821149312/1103332447876608

<<.PHP核心技術與最佳實踐>>

後續補充

...

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章