談談Websockt

>>>點擊獲取更多文章<<<javascript

歷史背景

在談Websockt以前,先談談推送技術。php

輪詢

它是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP請求,而後由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器須要不斷的向服務器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的數據可能只是很小的一部分,顯然這樣會浪費不少的帶寬等資源。html

Comet

比較新的技術去作輪詢,包括 長輪詢__,__iframe流 ,這種技術雖然能夠雙向通訊,但依然須要反覆發出請求。並且在Comet中,廣泛採用的長連接,也會消耗服務器資源。java

長輪詢

長輪詢是在打開一條鏈接之後保持,等待服務器推送來數據再關閉的方式。node

iframe流

iframe流方式是在頁面中插入一個隱藏的iframe,利用其src屬性在服務器和客戶端之間建立一條長連接,服務器向iframe傳輸數據(一般是HTML,內有負責插入信息的javascript),來實時更新頁面。python

iframe流方式的優勢是瀏覽器兼容好,Google公司在一些產品中使用了iframe流,如Google Talk。nginx

websockt的誕生

在這種狀況下,HTML5定義了WebSocket協議,能更好的節省服務器資源和帶寬,而且可以更實時地進行通信。git

協議標識

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

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

使用端口

Websocket使用和 HTTP 相同的 TCP 端口,能夠繞過大多數防火牆的限制。默認狀況下,Websocket協議使用80端口;運行在TLS之上時,默認使用443端口。web

ws://example.com:80/some/path    //80端口
wss://example.com:443/some/path     //443端口

簡介定義

WebSocket是一種在單個TCP鏈接上進行全雙工通訊的協議。

WebSocket 協議在2008年誕生,2011年成爲國際標準。全部瀏覽器都已經支持了。在WebSocket API中,瀏覽器和服務器只須要完成一次握手,二者之間就直接能夠建立持久性的鏈接,並進行雙向數據傳輸。它的最大特色就是,服務器能夠主動向客戶端推送信息,客戶端也能夠主動向服務器發送信息,是真正的雙向平等對話,屬於服務器推送技術的一種。

特色

  • 較少的控制開銷。在鏈接建立後,服務器和客戶端之間交換數據時,用於協議控制的數據包頭部相對較小。在不包含擴展的狀況下,對於服務器到客戶端的內容,此頭部大小隻有2至10字節(和數據包長度有關);對於客戶端到服務器的內容,此頭部還須要加上額外的4字節的掩碼。相對於HTTP請求每次都要攜帶完整的頭部,此項開銷顯著減小了。
  • 更強的實時性。因爲協議是全雙工的,因此服務器能夠隨時主動給客戶端下發數據。相對於HTTP請求須要等待客戶端發起請求服務端才能響應,延遲明顯更少;即便是和Comet等相似的長輪詢比較,其也能在短期內更屢次地傳遞數據。
  • 保持鏈接狀態。與HTTP不一樣的是,Websocket須要先建立鏈接,這就使得其成爲一種有狀態的協議,以後通訊時能夠省略部分狀態信息。而HTTP請求可能須要在每一個請求都攜帶狀態信息(如身份認證等)。
  • 上面前3點總結就是 數據格式比較輕量,性能開銷小,通訊高效。
  • 與 HTTP 協議有着良好的兼容性。默認端口也是80和443,而且握手階段採用 HTTP 協議,所以握手時不容易屏蔽,能經過各類 HTTP 代理服務器。
  • 能夠發送文本,也能夠發送二進制數據。
  • 沒有同源限制,客戶端能夠與任意服務器通訊。
  • 協議標識符是ws(若是加密,則爲wss),服務器網址就是 URL。

握手協議

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,以前草案的版本均應當棄用。

客戶端的簡單示例

下面是一個網頁腳本的例子,基本上一眼就能明白。

var ws = new WebSocket("wss://echo.websocket.org");

ws.onopen = function(evt) { 
  console.log("Connection open ..."); 
  ws.send("Hello WebSockets!");
};

ws.onmessage = function(evt) {
  console.log( "Received Message: " + evt.data);
  ws.close();
};

ws.onclose = function(evt) {
  console.log("Connection closed.");
};

其中 WebSocket 對象做爲一個構造函數,用於新建 WebSocket 實例。實例對象的全部屬性和方法清單,參見這裏

服務端的實現

在服務器方面,網上都有不一樣對websocket支持的服務器:

php-http://code.google.com/p/phpw...
jetty-http://jetty.codehaus.org/jetty/(版本7開始支持websocket)[永久失效連接]
netty-http://www.jboss.org/netty
ruby-http://github.com/gimite/web-...
Kaazing-https://web.archive.org/web/2...://www.kaazing.org/confluence/display/KAAZING/Home
Tomcat-http://tomcat.apache.org/(7.0.27支持websocket,建議用tomcat8,7.0.27中的接口已通過時)
WebLogic-http://www.oracle.com/us/prod...(12.1.2開始支持)[永久失效連接]
node.js-https://github.com/Worlize/We...
node.js-http://socket.io
nginx-http://nginx.com/
mojolicious-http://mojolicio.us/
python-https://github.com/abourget/g...
Django-https://github.com/stephenmcd...
erlang-https://github.com/ninenines/...

相關文章
相關標籤/搜索