WebSocket 是什麼原理?為什麼可以實現持久連線

weixin_34162629發表於2016-01-29
    你可以把 WebSocket 看成是 HTTP 協議為了支援長連線所打的一個大補丁,它和 HTTP 有一些共性,是為了解決 HTTP 本身無法解決的某些問題而做出的一個改良設計。在以前 HTTP 協議中所謂的 keep-alive connection 是指在一次 TCP 連線中完成多個 HTTP 請求,但是對每個請求仍然要單獨發 header;所謂的 polling 是指從客戶端(一般就是瀏覽器)不斷主動的向伺服器發 HTTP 請求查詢是否有新資料。這兩種模式有一個共同的缺點,就是除了真正的資料部分外,伺服器和客戶端還要大量交換 HTTP header,資訊交換效率很低。它們建立的“長連線”都是偽.長連線,只不過好處是不需要對現有的 HTTP server 和瀏覽器架構做修改就能實現。

WebSocket 解決的第一個問題是,通過第一個 HTTP request 建立了 TCP 連線之後,之後的交換資料都不需要再發 HTTP request了,使得這個長連線變成了一個真.長連線。但是不需要傳送 HTTP header就能交換資料顯然和原有的 HTTP 協議是有區別的,所以它需要對伺服器和客戶端都進行升級才能實現。在此基礎上 WebSocket 還是一個雙通道的連線,在同一個 TCP 連線上既可以發也可以收資訊。此外還有 multiplexing 功能,幾個不同的 URI 可以複用同一個 WebSocket 連線。這些都是原來的 HTTP 不能做到的。

另外說一點技術細節,因為看到有人提問 WebSocket 可能進入某種半死不活的狀態。這實際上也是原有網路世界的一些缺陷性設計。上面所說的 WebSocket 真.長連線雖然解決了伺服器和客戶端兩邊的問題,但坑爹的是網路應用除了伺服器和客戶端之外,另一個巨大的存在是中間的網路鏈路。一個 HTTP/WebSocket 連線往往要經過無數的路由,防火牆。你以為你的資料是在一個“連線”中傳送的,實際上它要跨越千山萬水,經過無數次轉發,過濾,才能最終抵達終點。在這過程中,中間節點的處理方法很可能會讓你意想不到。

比如說,這些坑爹的中間節點可能會認為一份連線在一段時間內沒有資料傳送就等於失效,它們會自作主張的切斷這些連線。在這種情況下,不論伺服器還是客戶端都不會收到任何提示,它們只會一廂情願的以為彼此間的紅線還在,徒勞地一邊又一邊地傳送抵達不了彼岸的資訊。而計算機網路協議棧的實現中又會有一層套一層的快取,除非填滿這些快取,你的程式根本不會發現任何錯誤。這樣,本來一個美好的 WebSocket 長連線,就可能在毫不知情的情況下進入了半死不活狀態。

而解決方案,WebSocket 的設計者們也早已想過。就是讓伺服器和客戶端能夠傳送 Ping/Pong Frame(RFC 6455 - The WebSocket Protocol)。這種 Frame 是一種特殊的資料包,它只包含一些後設資料而不需要真正的 Data Payload,可以在不影響 Application 的情況下維持住中間網路的連線狀態。

相關文章