摘要:概述本文是系列的第一篇,主要介紹相關(guān)的基礎(chǔ)協(xié)議知識(shí)和??蛻舳耸盏巾憫?yīng)后,立即發(fā)起下一次的請(qǐng)求。收到消息通過事件來接收消息。類型則需要傳遞一個(gè)對(duì)象作為參數(shù),相關(guān)的內(nèi)容也將在本系列第二篇中進(jìn)行介紹。
概述
本文是WebSocket系列的第一篇,主要介紹WebSocket相關(guān)的基礎(chǔ)協(xié)議知識(shí)和API。由于WebSocket的相關(guān)介紹在MDN中分布較亂,初學(xué)者不太容易入門,因此通過本文將相關(guān)基礎(chǔ)知識(shí)和使用方法進(jìn)行一個(gè)歸納和總結(jié)。
本文主要內(nèi)容如下:
WebSocket基礎(chǔ)概念介紹
WebSocket協(xié)議初讀
WebSocket 相關(guān)API淺析
WebSocket在線上項(xiàng)目中的使用
通過本文,你能夠了解到WebSocket相關(guān)基礎(chǔ)知識(shí),同時(shí)了解到WebSocket在線上環(huán)境中是如何使用的。
WebSocket介紹WebSockets 是一個(gè)可以創(chuàng)建和服務(wù)器間進(jìn)行雙向會(huì)話的高級(jí)技術(shù)。通過這個(gè)API你可以向服務(wù)器發(fā)送消息并接受基于事件驅(qū)動(dòng)的響應(yīng),這樣就不用向服務(wù)器輪詢獲取數(shù)據(jù)了。
上面是MDN中關(guān)于WebSocket的說明。其中雙向會(huì)話指的是客戶端和服務(wù)端都能夠通過WebSocket來進(jìn)行數(shù)據(jù)的互相傳遞,即服務(wù)端可以給客戶端推送數(shù)據(jù),客戶端也可以通過WebSocket來傳遞數(shù)據(jù)。
為什么要使用WebSocket在不使用WebSocket時(shí),如果我們需要建立一條長(zhǎng)連接,有以下幾種方法:
輪詢
長(zhǎng)輪詢(常用)
SSE(Server Send Event)
下面,我們對(duì)這幾個(gè)都進(jìn)行簡(jiǎn)單的介紹。
輪詢輪詢是最早在客戶端用來模擬長(zhǎng)連接的一種方式。他通過客戶端定時(shí)想服務(wù)端發(fā)送HTTP請(qǐng)求來模擬客戶端向服務(wù)端發(fā)送數(shù)據(jù),而服務(wù)端的數(shù)據(jù)則是在客戶端發(fā)送HTTP請(qǐng)求后跟隨返回。
這種方案能夠讓客戶端的數(shù)據(jù)幾乎實(shí)時(shí)的到達(dá),但是缺點(diǎn)也顯而易見:服務(wù)端的數(shù)據(jù)需要在客戶端的請(qǐng)求回來后才能帶回。如果HTTP請(qǐng)求的間隔太短,則會(huì)導(dǎo)致大量的網(wǎng)絡(luò)開銷;如果間隔太長(zhǎng),這將導(dǎo)致數(shù)據(jù)傳遞的不及時(shí)。
長(zhǎng)輪詢長(zhǎng)輪詢是在輪詢的基礎(chǔ)上改進(jìn)的一種方式。在客戶端發(fā)送HTTP請(qǐng)求且服務(wù)端收到請(qǐng)求時(shí),服務(wù)端會(huì)先維持這個(gè)請(qǐng)求不返回。在特定的時(shí)間內(nèi)(一般為30秒,因?yàn)橥ǔTTP判斷超時(shí)時(shí)間為30秒),如果服務(wù)端沒有數(shù)據(jù),則回應(yīng)這個(gè)請(qǐng)求;服務(wù)端有數(shù)據(jù)需要發(fā)送時(shí),則立即通過HTTP請(qǐng)求的響應(yīng)將數(shù)據(jù)傳遞給客戶端。客戶端收到響應(yīng)后,立即發(fā)起下一次的HTTP請(qǐng)求。
這種方案能夠解決輪詢中帶來的服務(wù)端數(shù)據(jù)不能及時(shí)傳遞的問題,但是帶來的網(wǎng)絡(luò)花銷大的問題仍然無法解決。
SSE(Server Send Event)SSE是一個(gè)新的協(xié)議,作用為服務(wù)端想客戶端推送數(shù)據(jù)。他通過自定義的SSE協(xié)議來實(shí)現(xiàn)單項(xiàng)的數(shù)據(jù)推送。SSE的缺點(diǎn)是數(shù)據(jù)只能從服務(wù)端像客戶端傳遞,而數(shù)據(jù)不能通過客戶端向服務(wù)端傳遞。
WebSocket能夠解決上述問題WebSocket能夠有效的解決以下問題:
帶寬問題:WebSocket相對(duì)于HTTP來說協(xié)議頭更加小,同時(shí)按需傳遞。
數(shù)據(jù)實(shí)時(shí)性問題:WebSocket相對(duì)于輪詢和長(zhǎng)輪詢來說,能夠?qū)崟r(shí)傳遞數(shù)據(jù),延遲更小。
狀態(tài)問題:相較于HTTP的無狀態(tài)請(qǐng)求,WebSocket在建立連接后能夠維持特定的狀態(tài)。
其他的優(yōu)點(diǎn)可以參考維基百科。
WebSocket協(xié)議了解了為什么需要使用WebSocket,下面讓我們來了解下WebSocket協(xié)議相關(guān)的內(nèi)容。
WebSocket協(xié)議是通過HTTP協(xié)議升級(jí)而來。只需要在HTTP協(xié)議基礎(chǔ)上增加兩次握手,即可建立WebSocket連接(如果是需要通過SSL加密,則還需要進(jìn)行SSL握手過程),握手的部分詳情可以見WebSocket文檔,下面我們簡(jiǎn)單介紹以下Header相關(guān)字段。
請(qǐng)求Header請(qǐng)求Header如下:
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: http://example.com Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13
其中:
Host: server.example.com:表示將要連接的WebSocket地址。
Connection: Upgrade:需要升級(jí)HTTP連接。
Upgrade: websocket:將HTTP連接升級(jí)至WebSocket連接。
Sec-WebSocket-Key:dGhlIHNhbXBsZSBub25jZQ== :客戶端生成的WebSocket連接密鑰。
Sec-WebSocket-Protocol: chat, superchat:指定哪些協(xié)議是客戶端可以接受的。
Sec-WebSocket-Version: 13:WebSocket版本號(hào)。
響應(yīng)HeaderHTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: chat
其中:
Upgrade: websocket:確認(rèn)將HTTP連接升級(jí)至WebSocket連接。
Connection: Upgrade:確認(rèn)升級(jí)HTTP連接。
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo:服務(wù)端根據(jù)客戶端的連接密鑰生成的服務(wù)端密鑰。
Sec-WebSocket-Protocol: chat:選擇的WebSocket協(xié)議。
WebSocket API介紹對(duì)WebSocket的協(xié)議有了一個(gè)初步的了解,下面讓我們看下,在具體的使用場(chǎng)景中,如何使用WebSocket。
WebSocket的API不多,下面我們就根據(jù)使用的順序:
建立連接
收到消息
發(fā)送消息
關(guān)閉連接
來逐一進(jìn)行介紹,具體的MDN資料可以見此處。
建立連接WebSocket通過初始化實(shí)例來建立連接,通過open事件回調(diào)函數(shù)來確認(rèn)連接建立成功,具體示例如下:
const webSocket = new WebSocket("ws://server.example.com"); webSocket.addEventListener("open", (event) => { // 建立連接成功 });
在WebSocket建立ws連接時(shí),url可以是域名或者IP地址;但是當(dāng)建立的連接是wss(加密WebSocket)時(shí),url必須是域名,因?yàn)樾枰渲孟鄳?yīng)的證書,而證書是針對(duì)域名的。
收到消息WebSocket通過message事件來接收消息。
socket.addEventListener("message", function (event) { console.log("Message from server", event.data); });
WebSocket可以傳遞String、ArrayBuffer和Blob三種數(shù)據(jù)類型,因此在收到消息時(shí)可能是其中的任意一種。其中,String和ArrayBuffer使用的最多。
如果是String類型,直接通過字符串處理函數(shù)即可進(jìn)行相關(guān)轉(zhuǎn)換,如JSON等格式。
如果是二進(jìn)制blob類型,則需要使用ArrayBuffer和DataView來進(jìn)行處理,相關(guān)的內(nèi)容將在本系列第二篇中進(jìn)行介紹。
發(fā)送消息WebSocket通過send方法來發(fā)送消息。
webSocket.send(data);
示例中的data字段,也有可能是收到消息所說的String、ArrayBuffer和Blob三種數(shù)據(jù)類型之一。
String類型只需要傳遞一個(gè)字符串給send方法作為參數(shù)即可。
ArrayBuffer類型則需要傳遞一個(gè)ArrayBuffer對(duì)象作為參數(shù),相關(guān)的內(nèi)容也將在本系列第二篇中進(jìn)行介紹。
關(guān)閉連接 被動(dòng)關(guān)閉當(dāng)服務(wù)端主動(dòng)關(guān)閉WebSocket連接時(shí),會(huì)通過WebSocket向客戶端發(fā)送一個(gè)close數(shù)據(jù)包,WebSocket的close事件會(huì)觸發(fā)。
webSocket.addEventListener("close", (closeEvent) => { });
注:當(dāng)網(wǎng)絡(luò)斷開時(shí),WebSocket連接并不會(huì)被動(dòng)關(guān)閉,因?yàn)闆]有收到關(guān)閉的數(shù)據(jù)包。
主動(dòng)關(guān)閉客戶端可以通過WebSocket提供的close方法來主動(dòng)關(guān)閉長(zhǎng)連接。
webSocket.close();
目前該方法有兩個(gè)參數(shù)(在某些版本中不支持,詳情見MDN文檔)):
第一個(gè)參數(shù)表示關(guān)閉連接的狀態(tài)號(hào),默認(rèn)為1000,表示正常關(guān)閉。
第二個(gè)參數(shù)為關(guān)閉原因,是一個(gè)不長(zhǎng)于123字節(jié)的UTF-8文本。
總結(jié)本文主要是介紹了一下WebSocket相關(guān)的基礎(chǔ)知識(shí)。
通過WebSocket的長(zhǎng)連接,客戶端和服務(wù)端可以進(jìn)行大量的數(shù)據(jù)傳輸而不會(huì)帶來相關(guān)的性能問題,這給Web端帶來了極大的功能增強(qiáng)。目前Web端可以使用WebSocket來進(jìn)行IM相關(guān)功能開發(fā),或者實(shí)時(shí)協(xié)作等需要與服務(wù)端進(jìn)行大量數(shù)據(jù)交互的功能,并且不需要像之前一樣使用長(zhǎng)輪詢的Hack方式來實(shí)現(xiàn)。
具體的使用方式和線上的使用問題,將會(huì)在本系列后幾篇博客中進(jìn)行介紹。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/93738.html
摘要:本文作為系列的第四篇內(nèi)容,將會(huì)用一個(gè)簡(jiǎn)單的聊天應(yīng)用把整個(gè)傳輸二進(jìn)制數(shù)據(jù)類型的內(nèi)容連接起來,讓用戶對(duì)整個(gè)傳輸二進(jìn)制數(shù)據(jù)的方法有個(gè)了解。如何發(fā)送二進(jìn)制數(shù)據(jù)通過如何設(shè)計(jì)一個(gè)二進(jìn)制協(xié)議一章,我們知道了如何定義傳輸?shù)亩M(jìn)制數(shù)據(jù)格式。 概述 通過前三篇博客,我們能夠了解在通過WebSocket發(fā)送數(shù)據(jù)之前,我們需要傳遞的數(shù)據(jù)是如何變成ArrayBuffer二進(jìn)制數(shù)據(jù)的;在我們收到二進(jìn)制數(shù)據(jù)之后,我...
摘要:與此同時(shí),后端服務(wù)的中也有相關(guān)的長(zhǎng)連接維持時(shí)長(zhǎng)設(shè)置。如何快速的恢復(fù)連接根據(jù)上面的操作方案,我們會(huì)在網(wǎng)絡(luò)異常時(shí)斷開連接。 概述 通過前四篇博客,相信讀者對(duì)于WebSocket的使用和數(shù)據(jù)(不論是ArrayBuffer還是String)傳輸都有了一個(gè)深刻的了解?,F(xiàn)在我們來介紹下,我在使用WebSocket時(shí),連接相關(guān)模塊遇到的一些共性問題,以及我們?nèi)绾谓鉀Q這些問題。 本文作為WebSock...
摘要:總結(jié)通過使用和,我們能夠在數(shù)據(jù)和二進(jìn)制數(shù)據(jù)中進(jìn)行互相轉(zhuǎn)換。下一篇系列相關(guān)的博客,將會(huì)介紹如何通過來向后端傳遞二進(jìn)制數(shù)據(jù),以及如何處理通過收到的二進(jìn)制數(shù)據(jù)。 概述 上一篇博客我們說到了如何進(jìn)行數(shù)字類型(如Short、Int、Long類型)如何在JavaScript中進(jìn)行二進(jìn)制轉(zhuǎn)換,如果感興趣的可以可以閱讀本系列第二篇博客——WebSocket系列之JavaScript中數(shù)字?jǐn)?shù)據(jù)如何轉(zhuǎn)換為...
摘要:以和為例,說明中的數(shù)字?jǐn)?shù)據(jù)如何轉(zhuǎn)換為二進(jìn)制數(shù)據(jù)。對(duì)象用來表示通用的固定長(zhǎng)度的原始二進(jìn)制數(shù)據(jù)緩沖區(qū)。中的數(shù)字?jǐn)?shù)據(jù)如何轉(zhuǎn)換為二進(jìn)制數(shù)據(jù)對(duì)和有了一個(gè)大概的了解,下面讓我們來看下它是如何進(jìn)行二進(jìn)制數(shù)據(jù)操作的。 概述 本文主要通過對(duì)JavaScript中數(shù)字?jǐn)?shù)據(jù)與二進(jìn)制數(shù)據(jù)之間的轉(zhuǎn)換,讓讀者能夠了解在JavaScript中如何對(duì)數(shù)字類型(包括但不限于Number類型)進(jìn)行處理。 二進(jìn)制數(shù)據(jù)在日常...
摘要:特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 本以為自己收藏的站點(diǎn)多,可以很快搞定,沒想到一入?yún)R總深似海。還有很多不足&遺漏的地方,歡迎補(bǔ)充。有錯(cuò)誤的地方,還請(qǐng)斧正... 托管: welcome to git,歡迎交流,感謝star 有好友反應(yīng)和斧正,會(huì)及時(shí)更新,平時(shí)業(yè)務(wù)工作時(shí)也會(huì)不定期更...
閱讀 3475·2023-04-25 18:52
閱讀 2488·2021-11-22 15:31
閱讀 1228·2021-10-22 09:54
閱讀 3016·2021-09-29 09:42
閱讀 611·2021-09-26 09:55
閱讀 915·2021-09-13 10:28
閱讀 1111·2019-08-30 15:56
閱讀 2111·2019-08-30 15:55