本頁使用了標題或全文手工轉換

WebSocket

維基百科,自由的百科全書
跳到: 導覽搜尋

WebSocket是一種在單個TCP連線上進行全雙工通訊的協定。WebSocket通訊協定於2011年被IETF定為標準RFC 6455,並由RFC7936補充規範。WebSocket API也被W3C定為標準。

WebSocket使得用戶端和伺服器之間的數據交換變得更加簡單,允許伺服端主動向用戶端推播數據。在WebSocket API中,瀏覽器和伺服器只需要完成一次交握,兩者之間就直接可以建立永續性的連線,並進行雙向數據傳輸。

背景[編輯]

現在,很多網站為了實現推播技術,所用的技術都是輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對伺服器發出HTTP請求,然後由伺服器返回最新的數據給用戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器需要不斷的向伺服器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的數據可能只是很小的一部分,顯然這樣會浪費很多的頻寬等資源。

而比較新的技術去做輪詢的效果是Comet。這種技術雖然可以雙向通訊,但依然需要反覆發出請求。而且在Comet中,普遍採用的長連結,也會消耗伺服器資源。

在這種情況下,HTML5定義了WebSocket協定,能更好的節省伺服器資源和頻寬,並且能夠更實時地進行通訊。

Websocket使用ws或wss的統一資源標誌符,類似於HTTPS,其中wss表示在TLS之上的Websocket。如:

ws://example.com/wsapi
wss://secure.example.com/

Websocket使用和 HTTP 相同的 TCP ,可以繞過大多數防火牆的限制。預設情況下,Websocket協定使用80埠;執行在TLS之上時,預設使用443埠。

優點[編輯]

  • 較少的控制開銷。在連線建立後,伺服器和用戶端之間交換數據時,用於協定控制的封包頭部相對較小。在不包含擴充功能的情況下,對於伺服器到用戶端的內容,此頭部大小只有2至10位元組(和封包長度有關);對於用戶端到伺服器的內容,此頭部還需要加上額外的4位元組的遮罩。相對於HTTP請求每次都要攜帶完整的頭部,此項開銷顯著減少了。
  • 更強的實時性。由於協定是全雙工的,所以伺服器可以隨時主動給用戶端下發數據。相對於HTTP請求需要等待用戶端發起請求伺服端才能響應,延遲明顯更少;即使是和Comet等類似的長輪詢比較,其也能在短時間內更多次地傳遞數據。
  • 保持連線狀態。於HTTP不同的是,Websocket需要先建立連線,這就使得其成為一種有狀態的協定,之後通訊時可以省略部分狀態資訊。而HTTP請求可能需要在每個請求都攜帶狀態資訊(如身份認證等)。
  • 更好的二進制支援。Websocket定義了二進制幀,相對HTTP,可以更輕鬆地處理二進制內容。
  • 可以支援擴充功能。Websocket定義了擴充功能,用戶可以擴充功能協定、實現部分自訂的子協定。如部分瀏覽器支援壓縮等。
  • 更好的壓縮效果。相對於HTTP壓縮,Websocket在適當的擴充功能支援下,可以沿用之前內容的上下文,在傳遞類似的數據時,可以顯着地提高壓縮率。[1]

交握協定[編輯]

WebSocket 是獨立的、建立在 TCP 上的協定。

Websocket 通過 HTTP/1.1 協定的101狀態碼進行交握。

為了建立Websocket連線,需要通過瀏覽器發出請求,之後伺服器進行回應,這個過程通常稱為「交握」(handshaking)。

例子[編輯]

一個典型的Websocket交握請求如下:

用戶端請求

GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13

伺服器回應

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
Sec-WebSocket-Location: ws://example.com/

欄位說明[編輯]

  • Connection必須設定Upgrade,表示用戶端希望連線升級。
  • Upgrade欄位必須設定Websocket,表示希望升級到Websocket協定。
  • Sec-WebSocket-Key是隨機的字串,伺服器端會用這些數據來構造出一個SHA-1的資訊摘要。把「Sec-WebSocket-Key」加上一個特殊字串「258EAFA5-E914-47DA-95CA-C5AB0DC85B11」,然後計算SHA-1摘要,之後進行BASE-64編碼,將結果做為「Sec-WebSocket-Accept」頭的值,返回給用戶端。如此操作,可以儘量避免普通HTTP請求被誤認為Websocket協定。
  • Sec-WebSocket-Version 表示支援的Websocket版本。RFC6455要求使用的版本是13,之前草案的版本均應當棄用。
  • Origin欄位是可選的,通常用來表示在瀏覽器中發起此Websocket連線所在的頁面,類似於Referer。但是,與Referer不同的是,Origin只包含了協定和主機名稱。
  • 其他一些定義在HTTP協定中的欄位,如Cookie等,也可以在Websocket中使用。

瀏覽器[編輯]

實現websocket的協定,瀏覽器扮演着一個很重要的角色。所有最新的瀏覽器支援最新規範(RFC 6455)的WebSocket協定。一個詳細的測試報告[2]列出了這些瀏覽器支援的Websocket版本。

瀏覽器支援現狀
協定 發佈日期 IE Firefox[3](個人電腦) Firefox (Android) Chrome(個人電腦,手機) Safari(Mac, iOS) Opera(個人電腦,手機) Android瀏覽器
hixie-75 2010年2月4日 4 5.0.0
hixie-76
hybi-00
2010年5月10日,
2010年5月23日
4.0(已禁用) 6 5.0.1 11.00(已禁用)
7 hybi-07 2011年4月22日 6[4]1
8 hybi-10 2011年7月11日 7[5]1 7 14[6]
13 RFC 6455 2011年12月 10[7] 11 11 16[8] 6 12.10[9] 4.4[10]

1基於Gecko 6–10版本的瀏覽器的WebSocket物件為「mozwebsocket」,[11]需要添加額外的代碼。

伺服器[編輯]

在伺服器方面,網上都有不同對websocket支援的伺服器:

參考資料[編輯]

  1. ^ https://tools.ietf.org/html/rfc7692
  2. ^ WebSockets協議測試報告. Tavendo.de. 2011-10-27 [2011-12-10]. 
  3. ^ WebSockets (support in Firefox). Developer.mozilla.org. 2011-09-30 [2011-12-10]. 
  4. ^ Bug 640003 - WebSockets - upgrade to ietf-06. Bugzilla.mozilla.org. [2011-12-10]. 
  5. ^ WebSockets - upgrade to ietf-07>
  6. ^ Chromium bug 64470. Code.google.com. 2010-11-25 [2011-12-10]. 
  7. ^ WebSockets in Windows Consumer Preview. IE Engineering Team. 2012-03-19 [2012-07-23]. 
  8. ^ WebKit Changeset 97247: WebSocket: Update WebSocket protocol to hybi-17. Trac.webkit.org. [2011-12-10]. 
  9. ^ A hot Opera 12.50 summer-time snapshot. Opera Developer News. [2012-08-03]. (原始內容存檔於2012-08-05). 
  10. ^ Compatibility tables for support of HTML5, CSS3, SVG and more in desktop and mobile browsers. caniuse.com. [2014-02-10]. 
  11. ^ WebSockets - MDN. Developer.mozilla.org. 2011-09-30 [2011-12-10].