WebSocket 之協議基礎

引言

隨着Web領域的飛速發展,最初設計得十分簡單的HTTP協議在當今的應用上顯得捉襟見肘,協議的瓶頸也逐漸顯露出來。web

「既然HTTP這麼爛?爲何咱們不拋棄它再設計一個全新的協議,而是要給他打補丁呢?」這是某次我和我舍友在宿舍喝着小酒,探討SpringMVC時談到的一個話題。spring

最初的HTTP,只是想把HTTP看成傳輸HTML文檔的協議,設計者沒有想到HTTP經久不衰,須要承受愈來愈複雜的業務職責。瀏覽器

因此HTTP的設計無可厚非,只是它不「那麼地」適應這個時代了。可是目前基於HTTP協議實現的Web瀏覽器遍及全球,並不能隨意動搖HTTP的地位。服務器

因此爲了知足現代社會日益增加的業務需求,涌現出無數企圖「消除」HTTP瓶頸的解決方案,其中的一項就是——「WebSocket」。微信

栗子

爲何會出現WebSocket協議呢?websocket

image.png

假設咱們去實現相似微信同樣的網頁在線聊天工具,咱們要解決什麼問題呢?網絡

很顯然,消息推送是當前業務場景下的一個技術瓶頸。異步

當前帳號收到了消息,咱們怎麼在網頁裏「實時地」獲取到消息並顯示呢?注意要保障在線聊天的實時性。socket

方案一:只使用HTTP

能實現嗎?顯然不能。spring-boot

瀏覽器向客戶端發起HTTP請求,請求到含有當前消息的HTML文件,渲染給用戶。請求結束,不考慮持久鏈接的狀況下,斷開TCP鏈接。

當服務器有新消息時,除非用戶當前網頁刷新,不然在只使用HTTP的狀況下沒法實現實時性。

方案二:再加上Ajax

Ajax意思就是用 JavaScript執行異步網絡請求。
——《廖雪峯的 JavaScript教程》

使用Ajax,能夠在瀏覽器內用JavaScript「偷偷」地發起網絡請求,查詢最新的消息,下降操做成本,提高用戶體驗。

爲了保證明時性,須要前臺定時發送Ajax請求。例如:每5s發送一次網絡請求查詢消息,將數據的延時性保持在固定間隔之內。

缺點很明顯,會產生大量的HTTP請求,若是消息長時間沒有更新,十分浪費通訊資源。

方案三:再加上Comet

爲了不產生大量無用的HTTP請求,產生了Comet

Ajax發起查詢消息的請求,服務器接收到該消息,不會當即響應,Comet會將響應置於掛起狀態,當服務器端有內容更新時,再返回響應。

與方案二相比,減小了無用的HTTP請求,同時也保證了數據的實時性。

缺點就是服務器壓力過大,服務器爲了保持掛起的HTTP響應,會消耗更多的寶貴的服務器資源。

方案四:WebSocket

由於HTTP是請求響應模式,因此若是是基於HTTP實現實時性,過於複雜。請求都是客戶端發起的,客戶端怎麼知道服務器的內容何時更新呢?

因此,2011年12月11日RFC 6455 - The WebSocket Protocol標準被確立。

WebSocket,一樣基於TCP協議,是Web瀏覽器與Web服務器之間的全雙工通訊標準。

若是有數據更新,服務器能夠向客戶端發送數據,使實現實時性變得簡單。

協議詳解

WebSocket鏈接的創建須要握手,說是握手,其實也是爲了兼容HTTP瀏覽器的一種手段。

握手之請求

客戶端向服務器發送HTTP數據包,請求創建握手。

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: xxxxxxxxxx
Sec-WebSocket-Version: 13

具體的細節我就不描述了,本身去查閱文檔。

客戶端發送HTTP請求,首部Upgrade: websocket,表示客戶端但願將通訊協議從HTTP升級爲WebSocket協議。

握手之響應

服務器返回響應,贊成切換協議。

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: xxxxxxxxxx

HTTP響應狀態碼101,切換協議。

通訊

握手以後即創建起了鏈接,開始全雙工通訊。

WebSocketHTTP協議相似,其資源地址相似:ws://server.example.com:8080/path

總結

本文共同討論了WebSocket協議的一些理論基礎,夜深了,先寫到這裏。

下一篇文章,使用spring-boot實現簡易的WebSocket示例。

相關文章
相關標籤/搜索