WebSocket是基於TCP的一種新的網絡協議,並在2011年被IETF定爲標準的全雙工通訊協議,它實現了客戶端與服務器全雙工通訊。javascript
WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,容許服務端主動向客戶端推送數據。在 WebSocket API 中,瀏覽器和服務器只須要完成一次握手,二者之間就直接能夠建立持久性的鏈接,並進行雙向數據傳輸。php
衆所周知,在WebSocket出現以前,不少網站爲了實現推送技術,所用的技術都是 Ajax 輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP請求,而後由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器須要不斷的向服務器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的數據可能只是很小的一部分,顯然這樣會浪費不少的帶寬等資源。而基於WebSocket 協議實現的客戶端和服務器之簡的通訊,能更好的節省服務器資源和帶寬,而且可以更實時地進行通信。html
瀏覽器經過 JavaScript 向服務器發出創建 WebSocket 鏈接的請求,鏈接創建之後,客戶端和服務器端就能夠經過 TCP 鏈接直接交換數據。java
當獲取 WebSocket 鏈接後,你能夠經過 send() 方法來向服務器發送數據,並經過 onmessage 事件來接收服務器返回的數據。使用 WebSocket API 建立 的WebSocket 對象的示例以下:node
var Socket = new WebSocket(url, [protocol] );
複製代碼
其中,第一個參數表示鏈接的URL,第二個參數 表示可接受的子協議。 Websocket 使用 ws 或 wss 的統一資源標誌符,相似於 HTTPS,其中 wss 表示在 TLS 之上的 Websocket。如:python
ws://example.com/wsapi
wss://secure.example.com/
複製代碼
Websocket 使用和 HTTP 相同的 TCP 端口,能夠繞過大多數防火牆的限制。默認狀況下,Websocket 協議使用 80 端口;運行在 TLS 之上時,默認使用 443 端口。nginx
下面是一個典型的Websocket握手請求實例:git
客戶端請求github
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13
複製代碼
服務器迴應web
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 中使用。
總的來講:Socket 是傳輸控制層協議,WebSocket 是應用層協議。
軟件通訊有七層結構,下三層結構偏向與數據通訊,上三層更偏向於數據處理,中間的傳輸層則是鏈接上三層與下三層之間的橋樑,每一層都作不一樣的工做,上層協議依賴與下層協議。基於這個通訊結構的概念。
Socket 其實並非一個協議,是應用層與 TCP/IP 協議族通訊的中間軟件抽象層,它是一組接口。當兩臺主機通訊時,讓 Socket 去組織數據,以符合指定的協議。TCP 鏈接則更依靠於底層的 IP 協議,IP 協議的鏈接則依賴於鏈路層等更低層次。
WebSocket具備以下屬性:Socket.readyState和Socket.bufferedAmount。 readyState 其中,readyState表示鏈接狀態,可能的值以下:
bufferedAmount bufferedAmount 表示已被 send() 放入正在隊列中等待傳輸,可是尚未發出的 UTF-8 文本字節數。
如下是 WebSocket 對象的相關事件。
WebSocket主要的方法有send()和close()。
爲了創建一個 WebSocket 鏈接,客戶端瀏覽器首先要向服務器發起一個 HTTP 請求,這個請求和一般的 HTTP 請求不一樣,包含了一些附加頭信息,其中附加頭信息"Upgrade: WebSocket"代表這是一個申請協議升級的 HTTP 請求,服務器端解析這些附加的頭信息而後產生應答信息返回給客戶端,客戶端和服務器端的 WebSocket 鏈接就創建起來了,雙方就能夠經過這個鏈接通道自由的傳遞信息,而且這個鏈接會持續存在直到客戶端或者服務器端的某一方主動的關閉鏈接。
首先,編寫一段客戶端代碼:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>菜鳥教程(runoob.com)</title>
<script type="text/javascript">
function WebSocketTest()
{
if ("WebSocket" in window)
{
alert("您的瀏覽器支持 WebSocket!");
// 打開一個 web socket
var ws = new WebSocket("ws://localhost:9998/echo");
ws.onopen = function()
{
// Web Socket 已鏈接上,使用 send() 方法發送數據
ws.send("發送數據");
alert("數據發送中...");
};
ws.onmessage = function (evt)
{
var received_msg = evt.data;
alert("數據已接收...");
};
ws.onclose = function()
{
// 關閉 websocket
alert("鏈接已關閉...");
};
}
else
{
// 瀏覽器不支持 WebSocket
alert("您的瀏覽器不支持 WebSocket!");
}
}
</script>
</head>
<body>
<div id="sse">
<a href="javascript:WebSocketTest()">運行 WebSocket</a>
</div>
</body>
</html>
複製代碼
在執行以上程序前,咱們須要建立一個支持 WebSocket 的服務。從 pywebsocket 下載 mod_pywebsocket ,或者使用 git 命令下載。
git clone https://github.com/google/pywebsocket.git
複製代碼
mod_pywebsocket 須要 python 環境支持,mod_pywebsocket 是一個 Apache HTTP 的 Web Socket擴展,安裝步驟以下: 進入 pywebsocket 目錄,執行以下命令:
$ python setup.py build
$ sudo python setup.py install
複製代碼
而後,在pywebsocket/mod_pywebsocket 目錄下執行如下命令開啓服務。
sudo python standalone.py -p 9998 -w ../example/
複製代碼
以上命令會開啓一個端口號爲 9998 的服務,使用 -w 來設置處理程序 echo_wsh.py 所在的目錄。 如今咱們能夠在 Chrome 瀏覽器打開前面建立的 runoob_websocket.html 文件。若是你的瀏覽器支持 WebSocket(), 點擊"運行 WebSocket",你就能夠看到整個流程各個步驟彈出的窗口,流程 Gif 演示:
在服務端開發方面,不一樣的語言對於Websockt的支持還略有差別,下面是參考連接:
php - code.google.com/p/phpwebsoc…
jetty - jetty.codehaus.org/jetty/(版本7開…
netty - www.jboss.org/netty
ruby - github.com/gimite/web-…
Kaazing - web.archive.org/web/2010092…
Tomcat - tomcat.apache.org/(7.0.27支持we…
WebLogic - www.oracle.com/us/products…
node.js - github.com/Worlize/Web…
node.js - socket.io
nginx - nginx.com/
mojolicious - mojolicio.us/
python - github.com/abourget/ge…
Django - github.com/stephenmcd/…
erlang - github.com/ninenines/c…