什麼是WebSocket?
- WebSocket 是 HTML5 開始提供的一種在單個 TCP 連接配接上進行全雙工通訊的協定。
- 在 WebSocket API中,浏覽器和伺服器隻需要完成一次握手,兩者就直接可以建立持久性的連接配接,并進行雙向資料傳輸。
- websocket彌補了HTTP不支援長連接配接的特點。
了解雙向通信
在WebSocket協定之前有三種實作雙向通信的方式:輪詢(polling)、長輪詢(long-polling)和 iframe流(streaming)。
- 輪詢:是用戶端和伺服器之間會一直進行連接配接,每隔一段時間就詢問一次。而且每次發送請求都會有Http的Header,會很耗流量,也會消耗CPU的使用率。
- 長輪詢:是對輪詢的改進版,用戶端發送HTTP給伺服器之後,看有沒有新消息,如果沒有新消息,就一直等待。當有新消息的時候,才會傳回給用戶端。- 優點:比 Polling 做了優化,有較好的時效性;
- iframe流:方式是在頁面中插入一個隐藏的iframe,利用其src屬性在伺服器和用戶端之間建立一條長連接配接,伺服器向iframe傳輸資料(通常是HTML,内有負責插入資訊的javascript),來實時更新頁面。
雙向通信的優缺點
通信方式 | 優點 | 缺點 |
---|---|---|
輪詢 | 實作簡單, 無需做過多的更改 | 輪詢的間隔過長,會導緻使用者不能及時接收到更新的資料; 輪詢的間隔過短,會導緻查詢請求過多,增加伺服器端的負擔 |
長輪詢 | 比輪詢做了優化,有較好的時效性 | 保持連接配接會消耗資源;伺服器沒有傳回有效資料,程式逾時 |
iframe流 | 消息能夠實時到達;浏覽器相容好 | 伺服器維護一個長連接配接會增加開銷;IE、chrome、Firefox會顯示加載沒有完成,圖示會不停旋轉 |
了解HTTP的局限性
iHTTP是半雙工協定,也就是說,在同一時刻資料隻能單向流動,用戶端向伺服器發送請求(單向的),然後伺服器響應請求(單向的)。
- 伺服器不能主動推送資料給浏覽器。這就會導緻一些進階功能難以實作,諸如聊天室場景就沒法實作。
WebSocket 的特點
- 支援雙向通信,實時性更強。
- 建立在 TCP 協定之上,伺服器端的實作比較容易。
- 與 HTTP 協定有着良好的相容性。預設端口也是80和443,并且握手階段采用 HTTP 協定,是以握手時不容易屏蔽,能通過各種 HTTP 代理伺服器。
- 可以發送文本,也可以發送二進制資料。
- 沒有同源限制,用戶端可以與任意伺服器通信。
- 協定辨別符是ws(如果加密,則為wss),伺服器網址就是 URL。
- 減少通信量:隻要建立起WebSocket連接配接,就希望一直保持連接配接狀态。
WebSocket 的使用
建立 WebSocket 對象
以上代碼中的第一個參數 url, 指定連接配接的 URL。第二個參數 protocol 是可選的,指定了可接受的子協定。
WebSocket 的屬性
屬性 | 描述 |
---|---|
Socket.readyState | 隻讀屬性 readyState 表示連接配接狀态:0 - 表示連接配接尚未建立。1 - 表示連接配接已建立,可以進行通信。2 - 表示連接配接正在進行關閉。3 - 表示連接配接已經關閉或者連接配接不能打開。 |
Socket.bufferedAmount | 隻讀屬性 bufferedAmount 已被 send() 放入正在隊列中等待傳輸,但是還沒有發出的 UTF-8 文本位元組數 |
WebSocket的事件
事件 | 事件處理程式 | 描述 |
---|---|---|
open | Socket.onopen | 連接配接建立時觸發 |
message | Socket.onmessage | 用戶端接收服務端資料時觸發 |
error | Socket.onerror | 通信發生錯誤時觸發 |
close | Socket.onclose | 連接配接關閉時觸發 |
WebSocket 方法
方法 | 描述 |
---|---|
Socket.send() | 使用連接配接發送資料 |
Socket.close() | 關閉連接配接 |
代碼示例
// 打開一個 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("連接配接已關閉...");
};
}