定義
1、websocket是html5的的一個(gè)重要組件阿趁;
2膜蛔、WebSocket 是一種基于ws協(xié)議的技術(shù)。使用它可以在客戶端與服務(wù)器之間建立一段連續(xù)的脖阵、全雙工的連接。它彌補(bǔ)了http不適合實(shí)時(shí)通信的重大缺陷墅茉。
特點(diǎn)
(1)服務(wù)器可以主動(dòng)向客戶端推送信息命黔,客戶端也可以主動(dòng)向服務(wù)器發(fā)送信息呜呐,是真正的雙向平等對(duì)話,屬于服務(wù)器推送技術(shù)的一種悍募。
(2)建立在 TCP 協(xié)議之上蘑辑,服務(wù)器端的實(shí)現(xiàn)比較容易。
(3)與 HTTP 協(xié)議有著良好的兼容性坠宴。默認(rèn)端口也是80和443洋魂,并且握手階段采用 HTTP 協(xié)議,因此握手時(shí)不容易屏蔽喜鼓,能通過(guò)各種 HTTP 代理服務(wù)器副砍。
(4)數(shù)據(jù)格式比較輕量,性能開(kāi)銷小庄岖,通信高效豁翎。
(5)可以發(fā)送文本,也可以發(fā)送二進(jìn)制數(shù)據(jù)隅忿。
(6)沒(méi)有同源限制心剥,客戶端可以與任意服務(wù)器通信。
(7)協(xié)議標(biāo)識(shí)符是ws(如果加密背桐,則為wss)优烧,服務(wù)器網(wǎng)址就是 URL。
協(xié)議的握手過(guò)程
在客戶端和服務(wù)端一開(kāi)始握手的期間链峭,http協(xié)議升級(jí)到WebSocket協(xié)議就建立了連接畦娄,底層都是TCP協(xié)議。一旦建立連接熏版,通過(guò)WebSocket接口可以反復(fù)的發(fā)送消息纷责。
為了建立WebSocket連接,客戶端發(fā)送WebSocket握手請(qǐng)求撼短,服務(wù)器返回一個(gè)WebSocket握手響應(yīng)再膳;
客戶端請(qǐng)求:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
服務(wù)端響應(yīng):
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
websocket API
創(chuàng)建websocket實(shí)例
首先,我們需要通過(guò)調(diào)用WebSocket構(gòu)造函數(shù)來(lái)創(chuàng)建一個(gè)WebSocket連接曲横,構(gòu)造函數(shù)會(huì)返回一個(gè)WebSocket實(shí)例喂柒,可以用來(lái)監(jiān)聽(tīng)事件。這些事件會(huì)告訴你什么時(shí)候連接建立禾嫉,什么時(shí)候消息到達(dá)灾杰,什么時(shí)候連接關(guān)閉了,以及什么時(shí)候發(fā)生了錯(cuò)誤熙参。WebSocket協(xié)議定義了兩種URL方案艳吠,WS和WSS分別代表了客戶端和服務(wù)端之間未加密和加密的通信。WS(WebSocket)類似于Http URL孽椰,而WSS(WebSocket Security)URL 表示連接是基于安全傳輸層(TLS/SSL)和https的連接是同樣的安全機(jī)制昭娩。
WebSocket的構(gòu)造函數(shù)需要一個(gè)URL參數(shù)和一個(gè)可選的協(xié)議參數(shù)(一個(gè)或者多個(gè)協(xié)議的名字)凛篙,協(xié)議的參數(shù)例如XMPP(Extensible Messaging and Presence Protocol)、SOAP(Simple Object Access Protocol)或者自定義協(xié)議栏渺,服務(wù)端和客服端使用的協(xié)議必須一致呛梆,這樣收發(fā)消息彼此才能理解。而URL參數(shù)需要以WS://或者WSS://開(kāi)頭磕诊,例如:ws://www.websocket.org填物,如果URL有語(yǔ)法錯(cuò)誤,構(gòu)造函數(shù)會(huì)拋出異常霎终。
// WebSocket 對(duì)象作為一個(gè)構(gòu)造函數(shù)滞磺,用于新建 WebSocket 實(shí)例
const ws = new WebSocket('ws://localhost:8282');
websocket事件
WebSocket API是純事件驅(qū)動(dòng),通過(guò)監(jiān)聽(tīng)事件可以處理到來(lái)的數(shù)據(jù)和改變的鏈接狀態(tài)神僵⊙闼ⅲ客戶端不需要為了更新數(shù)據(jù)而輪訓(xùn)服務(wù)器。服務(wù)端發(fā)送數(shù)據(jù)后保礼,消息和事件會(huì)異步到達(dá)沛励。WebSocket編程遵循一個(gè)異步編程模型,只需要對(duì)WebSocket對(duì)象增加回調(diào)函數(shù)就可以監(jiān)聽(tīng)事件炮障。你也可以使用addEventListener()方法來(lái)監(jiān)聽(tīng)目派。
Open
一旦服務(wù)端響應(yīng)WebSocket連接請(qǐng)求,就會(huì)觸發(fā)open事件胁赢。響應(yīng)的回調(diào)函數(shù)稱為onopen企蹭。
ws.onopen=function(){
console.log('connection is opened!');
}
// 指定多個(gè)回調(diào)函數(shù)
ws.addEventListener('open', function (event) {
console.log(‘connection is open!’)智末;
});
open事件觸發(fā)的時(shí)候谅摄,意味著協(xié)議握手結(jié)束,WebSocket已經(jīng)準(zhǔn)備好收發(fā)數(shù)據(jù)系馆。如果你的應(yīng)用收到open事件送漠,就可以確定服務(wù)端已經(jīng)處理了建立連接的請(qǐng)求,且同意和你的應(yīng)用通信由蘑。
Message
當(dāng)消息被接受會(huì)觸發(fā)消息事件闽寡,響應(yīng)的回調(diào)函數(shù)叫做onmessage。接收的消息類型有文本信息尼酿、二進(jìn)制數(shù)據(jù)(blob和ArrayBuffer兩種類型)爷狈。
ws.onmessage = function(e) {
const data = e.data;
}
Error
如果發(fā)生意外的失敗會(huì)觸發(fā)error事件,相應(yīng)的函數(shù)稱為onerror,錯(cuò)誤會(huì)導(dǎo)致連接關(guān)閉裳擎。如果你收到一個(gè)錯(cuò)誤事件涎永,那么你很快會(huì)收到一個(gè)關(guān)閉事件,在關(guān)閉事件中也許會(huì)告訴你錯(cuò)誤的原因。
ws.onerror = function(e){
console.log('websocket error', e);
handleErrors(e);
}
Close
當(dāng)連接關(guān)閉的時(shí)候回觸發(fā)這個(gè)事件土辩,對(duì)應(yīng)onclose方法支救,連接關(guān)閉之后抢野,服務(wù)端和客戶端就不能再收發(fā)消息拷淘。
ws.onclose=function(e){
console.log('websocket closed', e);
console.log(e.code);
console.log(e.reason);
console.log(e.wasClean);
}
關(guān)閉事件有三個(gè)屬性可以用來(lái)做異常處理和重獲: wasClean,code和reason。wasClean是一個(gè)bool值指孤,代表連接是否干凈的關(guān)閉启涯。 如果是響應(yīng)服務(wù)端的close事件,這個(gè)值為true恃轩,如果是別的原因结洼,比如因?yàn)槭堑讓覶CP連接關(guān)閉,wasClean為false叉跛。code和reason代表關(guān)閉連接時(shí)服務(wù)端發(fā)送的狀態(tài);
websocket方法
ws.send()
一旦建立了連接松忍,實(shí)例對(duì)象的send()方法可用于向服務(wù)器發(fā)送數(shù)據(jù)。(文本筷厘、blob對(duì)象鸣峭、ArrayBuffer對(duì)象:類型化數(shù)組)
ws.send('message');
ws.close()
使用close方法來(lái)關(guān)閉連接,如果連接已經(jīng)關(guān)閉酥艳,這方法將什么也不做摊溶。調(diào)用close方法之后,將不能發(fā)送數(shù)據(jù)充石。
websocket屬性
WebSocket對(duì)象有三個(gè)屬性莫换,readyState,bufferedAmount和Protocol骤铃。
readyState 常量
返回實(shí)例對(duì)象的當(dāng)前狀態(tài)拉岁,共有四種
CONNECTING:值為0,表示正在連接惰爬。
OPEN:值為1喊暖,表示連接成功,可以通信了补鼻。
CLOSING:值為2哄啄,表示連接正在關(guān)閉。
CLOSED:值為3风范,表示連接已經(jīng)關(guān)閉咨跌,或者打開(kāi)連接失敗。
bufferedAmount
有時(shí)候需要檢查傳輸數(shù)據(jù)的大小硼婿,尤其是客戶端傳輸大量數(shù)據(jù)的時(shí)候锌半。雖然send()方法會(huì)馬上執(zhí)行,但數(shù)據(jù)并不是馬上傳輸寇漫。瀏覽器會(huì)緩存應(yīng)用流出的數(shù)據(jù)刊殉,你可以使用bufferedAmount屬性檢查已經(jīng)進(jìn)入隊(duì)列但還未被傳輸?shù)臄?shù)據(jù)大小殉摔。
protocol
在構(gòu)造函數(shù)中,protocol參數(shù)讓服務(wù)端知道客戶端使用的WebSocket協(xié)議记焊。而WebSocket對(duì)象的這個(gè)屬性就是指的最終服務(wù)端確定下來(lái)的協(xié)議名稱逸月,當(dāng)服務(wù)端沒(méi)有選擇客戶端提供的協(xié)議或者在連接握手結(jié)束之前,這個(gè)屬性都是空的遍膜。
ws.onopen=function(){
console.log(ws.protocol);
}