WebSocket 是什么于微?
WebSocket 是一種網絡通信協(xié)議。RFC6455 定義了它的通信標準。
WebSocket 是 HTML5 開始提供的一種在單個 TCP 連接上進行全雙工通訊的協(xié)議等脂。
為什么需要 WebSocket 裁奇?
了解計算機網絡協(xié)議的人桐猬,應該都知道:HTTP 協(xié)議是一種無狀態(tài)的、無連接的刽肠、單向的應用層協(xié)議溃肪。它采用了請求/響應模型。通信請求只能由客戶端發(fā)起音五,服務端對請求做出應答處理惫撰。
這種通信模型有一個弊端:HTTP 協(xié)議無法實現(xiàn)服務器主動向客戶端發(fā)起消息。
這種單向請求的特點躺涝,注定了如果服務器有連續(xù)的狀態(tài)變化厨钻,客戶端要獲知就非常麻煩。大多數(shù) Web 應用程序將通過頻繁的異步 JavaScript 和 XML(AJAX)請求實現(xiàn)長輪詢。輪詢的效率低莉撇,非常浪費資源(因為必須不停連接呢蛤,或者 HTTP 連接始終打開)。
因此棍郎,工程師們一直在思考其障,有沒有更好的方法。WebSocket 就是這樣發(fā)明的涂佃。WebSocket 連接允許客戶端和服務器之間進行全雙工通信励翼,以便任一方都可以通過建立的連接將數(shù)據(jù)推送到另一端。WebSocket 只需要建立一次連接辜荠,就可以一直保持連接狀態(tài)汽抚。這相比于輪詢方式的不停建立連接顯然效率要大大提高。
WebSocket 如何工作伯病?
Web 瀏覽器和服務器都必須實現(xiàn) WebSockets 協(xié)議來建立和維護連接造烁。由于 WebSockets 連接長期存在,與典型的 HTTP 連接不同午笛,對服務器有重要的影響惭蟋。
基于多線程或多進程的服務器無法適用于 WebSockets,因為它旨在打開連接药磺,盡可能快地處理請求告组,然后關閉連接。任何實際的 WebSockets 服務器端實現(xiàn)都需要一個異步服務器癌佩。
WebSocket 客戶端
- 在客戶端木缝,沒有必要為 WebSockets 使用 JavaScript 庫。實現(xiàn) WebSockets 的 Web 瀏覽器將通過 WebSockets 對象公開所有必需的客戶端功能(主要指支持 Html5 的瀏覽器)围辙。
客戶端 API
- 以下 API 用于創(chuàng)建 WebSocket 對象我碟。
/*
* param
* url@ 指定連接的 URL
* protocol@ 是可選的,指定了可接受的子協(xié)議
*/
var Socket = new WebSocket(url, [protocol])
WebSocket 屬性
以下是 WebSocket 對象的屬性姚建。假定我們使用了以上代碼創(chuàng)建了 Socket 對象:
屬性 | 描述 |
---|---|
Socket.readyState | 只讀屬性 readyState 表示連接狀態(tài)怎囚,可以是以下值:0 - 表示連接尚未建立。1 - 表示連接已建立桥胞,可以進行通信恳守。2 - 表示連接正在進行關閉。3 - 表示連接已經關閉或者連接不能打開贩虾。 |
Socket.bufferedAmount | 只讀屬性 bufferedAmount 已被 send() 放入正在隊列中等待傳輸催烘,但是還沒有發(fā)出的 UTF-8 文本字節(jié)數(shù)。 |
WebSocket 事件
以下是 WebSocket 對象的相關事件缎罢。假定我們使用了以上代碼創(chuàng)建了 Socket 對象:
事件 | 事件處理程序 | 描述 |
---|---|---|
open | Socket.onopen | 連接建立時觸發(fā) |
message | Socket.onmessage | 客戶端接收服務端數(shù)據(jù)時觸發(fā) |
error | Socket.onerror | 通信發(fā)生錯誤時觸發(fā) |
close | Socket.onclose | 連接關閉時觸發(fā) |
WebSocket 方法
以下是 WebSocket 對象的相關方法伊群。假定我們使用了以上代碼創(chuàng)建了 Socket 對象:
方法 | 描述 |
---|---|
Socket.send() | 使用連接發(fā)送數(shù)據(jù) |
Socket.close() | 關閉連接 |
示例
// 初始化一個 WebSocket 對象
var ws = new WebSocket('ws://localhost:9998/echo')
// 建立 web socket 連接成功觸發(fā)事件
ws.onopen = function() {
// 使用 send() 方法發(fā)送數(shù)據(jù)
ws.send('發(fā)送數(shù)據(jù)')
alert('數(shù)據(jù)發(fā)送中...')
}
// 接收服務端數(shù)據(jù)時觸發(fā)事件
ws.onmessage = function(evt) {
var received_msg = evt.data
alert('數(shù)據(jù)已接收...')
}
// 斷開 web socket 連接成功觸發(fā)事件
ws.onclose = function() {
alert('連接已關閉...')
}
其他特點包括:
建立在 TCP 協(xié)議之上考杉,服務器端的實現(xiàn)比較容易。
與 HTTP 協(xié)議有著良好的兼容性舰始。默認端口也是80和443崇棠,并且握手階段采用 HTTP 協(xié)議,因此握手時不容易屏蔽丸卷,能通過各種 HTTP 代理服務器枕稀。
數(shù)據(jù)格式比較輕量,性能開銷小谜嫉,通信高效萎坷。
可以發(fā)送文本,也可以發(fā)送二進制數(shù)據(jù)沐兰。
沒有同源限制哆档,客戶端可以與任意服務器通信。
協(xié)議標識符是ws(如果加密住闯,則為wss)瓜浸,服務器網址就是 URL。