一并思、什么是WebScoket??
WebSocket 是一種網(wǎng)絡(luò)傳輸協(xié)議,可在單個(gè) TCP 連接上進(jìn)行全雙工通信语稠,位于 OSI 模型的應(yīng)用層宋彼。WebSocket 使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù)颅筋。在 WebSocket API 中宙暇,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就可以創(chuàng)建持久性的連接议泵,并進(jìn)行雙向數(shù)據(jù)傳輸占贫。
下圖是輪詢與websocket的區(qū)別
1.2、WebSocket 優(yōu)點(diǎn)
- 較少的控制開銷先口。在連接創(chuàng)建后型奥,服務(wù)器和客戶端之間交換數(shù)據(jù)時(shí),用于協(xié)議控制的數(shù)據(jù)包頭部相對(duì)較小碉京。
- 更強(qiáng)的實(shí)時(shí)性厢汹。由于協(xié)議是全雙工的,所以服務(wù)器可以隨時(shí)主動(dòng)給客戶端下發(fā)數(shù)據(jù)谐宙。相對(duì)于 HTTP 請(qǐng)求需要等待客戶端發(fā)起請(qǐng)求服務(wù)端才能響應(yīng)烫葬,延遲明顯更少。
- 保持連接狀態(tài)凡蜻。與 HTTP 不同的是搭综,WebSocket 需要先創(chuàng)建連接,這就使得其成為一種有狀態(tài)的協(xié)議划栓,之后通信時(shí)可以省略部分狀態(tài)信息兑巾。
- 更好的二進(jìn)制支持。WebSocket 定義了二進(jìn)制幀忠荞,相對(duì) HTTP蒋歌,可以更輕松地處理二進(jìn)制內(nèi)容。
- 可以支持?jǐn)U展委煤。WebSocket 定義了擴(kuò)展堂油,用戶可以擴(kuò)展協(xié)議、實(shí)現(xiàn)部分自定義的子協(xié)議素标。
二称诗、WebScoket API??
在瀏覽器中要使用 WebSocket 提供的能力,我們就必須先創(chuàng)建 WebSocket 對(duì)象头遭,該對(duì)象提供了用于創(chuàng)建和管理 WebSocket 連接寓免,以及可以通過該連接發(fā)送和接收數(shù)據(jù)的 API癣诱。
2.1、構(gòu)造函數(shù)
const myWebSocket = new WebSocket(url [, protocols]);
- url:表示連接的 URL袜香,這是 WebSocket 服務(wù)器將響應(yīng)的 URL
- protocols(可選):一個(gè)協(xié)議字符串或者一個(gè)包含協(xié)議字符串的數(shù)組撕予。這些字符串用于指定子協(xié)議,這樣單個(gè)服務(wù)器可以實(shí)現(xiàn)多個(gè) WebSocket 子協(xié)議蜈首。比如实抡,你可能希望一臺(tái)服務(wù)器能夠根據(jù)指定的協(xié)議(protocol)處理不同類型的交互。如果不指定協(xié)議字符串欢策,則假定為空字符串吆寨。
2.2、屬性
WebSocket 對(duì)象包含以下屬性:每個(gè)屬性的具體含義如下:
- binaryType:使用二進(jìn)制的數(shù)據(jù)類型連接踩寇。
- bufferedAmount(只讀):未發(fā)送至服務(wù)器的字節(jié)數(shù)啄清。
- extensions(只讀):服務(wù)器選擇的擴(kuò)展。
- onclose:用于指定連接關(guān)閉后的回調(diào)函數(shù)俺孙。
- onerror:用于指定連接失敗后的回調(diào)函數(shù)辣卒。
- onmessage:用于指定當(dāng)從服務(wù)器接受到信息時(shí)的回調(diào)函數(shù)。
- onopen:用于指定連接成功后的回調(diào)函數(shù)睛榄。
- protocol(只讀):用于返回服務(wù)器端選中的子協(xié)議的名字荣茫。
- readyState(只讀):返回當(dāng)前 WebSocket 的連接狀態(tài),共有 4 種狀態(tài):
CONNECTING — 正在連接中场靴,對(duì)應(yīng)的值為 0啡莉;
OPEN — 已經(jīng)連接并且可以通訊,對(duì)應(yīng)的值為 1旨剥;
CLOSING — 連接正在關(guān)閉票罐,對(duì)應(yīng)的值為 2;
CLOSED — 連接已關(guān)閉或者沒有連接成功泞边,對(duì)應(yīng)的值為 3。
- url(只讀):返回值為當(dāng)構(gòu)造函數(shù)創(chuàng)建 WebSocket 實(shí)例對(duì)象時(shí) URL 的絕對(duì)路徑疗杉。
2.3阵谚、方法
- close([code[, reason]]):該方法用于關(guān)閉 WebSocket 連接,如果連接已經(jīng)關(guān)閉烟具,則此方法不執(zhí)行任何操作梢什。
- send(data):該方法將需要通過 WebSocket 鏈接傳輸至服務(wù)器的數(shù)據(jù)排入隊(duì)列,并根據(jù)所需要傳輸?shù)臄?shù)據(jù)的大小來增加 bufferedAmount 的值 朝聋。若數(shù)據(jù)無法傳輸(比如數(shù)據(jù)需要緩存而緩沖區(qū)已滿)時(shí)嗡午,套接字會(huì)自行關(guān)閉。
2.4冀痕、 事件
使用 addEventListener() 或?qū)⒁粋€(gè)事件監(jiān)聽器賦值給 WebSocket 對(duì)象的 oneventname 屬性荔睹,來監(jiān)聽下面的事件狸演。
- close:當(dāng)一個(gè) WebSocket 連接被關(guān)閉時(shí)觸發(fā),也可以通過 onclose 屬性來設(shè)置僻他。
- error:當(dāng)一個(gè) WebSocket 連接因錯(cuò)誤而關(guān)閉時(shí)觸發(fā)宵距,也可以通過 onerror 屬性來設(shè)置。
- message:當(dāng)通過 WebSocket 收到數(shù)據(jù)時(shí)觸發(fā)吨拗,也可以通過 onmessage 屬性來設(shè)置满哪。
- open:當(dāng)一個(gè) WebSocket 連接成功時(shí)觸發(fā),也可以通過 onopen 屬性來設(shè)置劝篷。
三哨鸭、其他???♀?
3.1、WebSocket 與 HTTP 有什么關(guān)系
WebSocket 是一種與 HTTP 不同的協(xié)議娇妓。兩者都位于 OSI 模型的應(yīng)用層像鸡,并且都依賴于傳輸層的 TCP 協(xié)議。 雖然它們不同峡蟋,但是 RFC 6455 中規(guī)定:WebSocket 被設(shè)計(jì)為在 HTTP 80 和 443 端口上工作坟桅,并支持 HTTP 代理和中介,從而使其與 HTTP 協(xié)議兼容蕊蝗。 為了實(shí)現(xiàn)兼容性仅乓,WebSocket 握手使用 HTTP Upgrade 頭,從 HTTP 協(xié)議更改為 WebSocket 協(xié)議蓬戚。
3.2夸楣、WebSocket 與長輪詢有什么區(qū)別
長輪詢就是客戶端發(fā)起一個(gè)請(qǐng)求,服務(wù)器收到客戶端發(fā)來的請(qǐng)求后子漩,服務(wù)器端不會(huì)直接進(jìn)行響應(yīng)豫喧,而是先將這個(gè)請(qǐng)求掛起,然后判斷請(qǐng)求的數(shù)據(jù)是否有更新幢泼。如果有更新紧显,則進(jìn)行響應(yīng),如果一直沒有數(shù)據(jù)缕棵,則等待一定的時(shí)間后才返回孵班。
長輪詢的本質(zhì)還是基于 HTTP 協(xié)議,它仍然是一個(gè)一問一答(請(qǐng)求 — 響應(yīng))的模式招驴。而 WebSocket 在握手成功后篙程,就是全雙工的 TCP 通道,數(shù)據(jù)可以主動(dòng)從服務(wù)端發(fā)送到客戶端别厘。
3.3虱饿、什么是 WebSocket 心跳
網(wǎng)絡(luò)中的接收和發(fā)送數(shù)據(jù)都是使用 SOCKET 進(jìn)行實(shí)現(xiàn)。但是如果此套接字已經(jīng)斷開,那發(fā)送數(shù)據(jù)和接收數(shù)據(jù)的時(shí)候就一定會(huì)有問題氮发】嗜猓可是如何判斷這個(gè)套接字是否還可以使用呢?這個(gè)就需要在系統(tǒng)中創(chuàng)建心跳機(jī)制折柠。所謂 “心跳” 就是定時(shí)發(fā)送一個(gè)自定義的結(jié)構(gòu)體(心跳包或心跳幀)宾娜,讓對(duì)方知道自己 “在線”。 以確保鏈接的有效性扇售。
而所謂的心跳包就是客戶端定時(shí)發(fā)送簡單的信息給服務(wù)器端告訴它我還在而已前塔。代碼就是每隔幾分鐘發(fā)送一個(gè)固定信息給服務(wù)端,服務(wù)端收到后回復(fù)一個(gè)固定信息承冰,如果服務(wù)端幾分鐘內(nèi)沒有收到客戶端信息則視客戶端斷開华弓。
在 WebSocket 協(xié)議中定義了 心跳 Ping 和 心跳 Pong 的控制幀:
- 心跳 Ping 幀包含的操作碼是 0x9。如果收到了一個(gè)心跳 Ping 幀困乒,那么終端必須發(fā)送一個(gè)心跳 Pong 幀作為回應(yīng)寂屏,除非已經(jīng)收到了一個(gè)關(guān)閉幀。否則終端應(yīng)該盡快回復(fù) Pong 幀娜搂。
- 心跳 Pong 幀包含的操作碼是 0xA迁霎。作為回應(yīng)發(fā)送的 Pong 幀必須完整攜帶 Ping 幀中傳遞過來的 “應(yīng)用數(shù)據(jù)” 字段。如果終端收到一個(gè) Ping 幀但是沒有發(fā)送 Pong 幀來回應(yīng)之前的 Ping 幀百宇,那么終端可以選擇僅為最近處理的 Ping 幀發(fā)送 Pong 幀考廉。此外,可以自動(dòng)發(fā)送一個(gè) Pong 幀携御,這用作單向心跳昌粤。