服務器推送技術與websocket協議

websocket 作為現代瀏覽器的長連接標準,可以很好的解決瀏覽器與服務器實時通訊的問題,那麼在 websocket 出現之前是怎麼解決這個問題的呢?首先來回顧一下在此之前瀏覽器和服務器的”長連接”之路。

回顧

在 websocket 協議出來之前,主要是有三種方向去實現類似 websocket 的功能的。

Flash

flash 支持 socket 通訊功能,基於 flash 可以很簡單的實現與服務器建立通訊。

  • 優點:開發簡單、兼容性高
  • 缺點:需要瀏覽器啟用 flash 功能,並且逐漸被瀏覽器淘汰

AJAX Polling

瀏覽器使用 ajax 去輪詢服務器,服務器有內容就返回,輪詢也分為短輪詢和長輪詢。

短輪詢

短輪詢即瀏覽器通過 ajax 按照一定時間的間隔去請求服務器,服務器會立即響應,不管有沒有可用數據。

  • 流程圖:
  • 優點:短鏈接、服務器處理方便。
  • 缺點:實時性低、很多無效請求、性能開銷大

長輪詢

長短輪詢則是瀏覽器通過 ajax 與服務器建立連接,服務器在沒有數據返回時一直阻塞著,直到有數據之後才返回響應。

  • 流程圖:
  • 優點:實時性高
  • 缺點:每個連接只能返回一次數據

COMET

comet 也是常用的一種服務器推送技術,主要的原理是通過 HTTP Chunked 響應,將消息源源不斷的推送給瀏覽器,通常情況下服務器返回的響應內容都是定長的,會使用 Content-Length 來指定響應報文的長度,而 Chunked 編碼的響應則是通過一種特殊的編碼,只要瀏覽器沒有遇到結束標識,就會邊解析邊執行對應的響應內容。

  • chunked 編碼報文示例:
<code>HTTP/1.1 200 OK
Content-Type: text/html
Date: Thu, 08 Aug 2019 02:50:06 GMT
Transfer-Encoding: chunked

11
callback('data1')
11
callback('data2')
0
/<code>

報文格式為:

<code>\r\n
\r\n
\r\n
\r\n
...
0\r\n
/<code>

由 16 進制的數字來標識一個 chunk data 數據的長度,在讀取到 0\r\n 時結束,通過一直讀取 chunk data 來執行 js 代碼,從而向客戶端推送數據。

  • go 語言實現:
<code>func main() {
	http.HandleFunc("/push", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		flusher := w.(http.Flusher)
		w.Write([]byte(" "))
		flusher.Flush()
		// 延遲一秒,以便觀察瀏覽器的邊解析邊執行
		time.Sleep(time.Second)
		w.Write([]byte(" "))
		flusher.Flush()
	})
	log.Fatal(http.ListenAndServe(":8080", nil))
}
/<code>

通過 iframe 實現

iframe 實現是通過隱藏一個 ,通過 iframe 連接到服務器,服務器響應帶有


分享到:


相關文章: