一、webSocket
The HTML5 WebSockets specification defines an API that enables web pages to use the WebSockets protocol for two-way communication with a remote host. HTML5 WebSockets provide an enormous reduction in unnecessary network traffic and latency compared to the unscalable polling and long-polling solutions that were used to simulate a full-duplex connection by maintaining two connections.
讓我們先來(lái)了解一下全雙工和半雙工的概念瓮床,說(shuō)實(shí)話(huà)橄务,有點(diǎn)忘了疟赊,當(dāng)年可是必考題楚午!網(wǎng)絡(luò)老師聽(tīng)了差點(diǎn)想打人踪古。祖灰。钟沛。
全雙工(full-duplex):
假設(shè)在交換機(jī)通信兩端為A和B,在全雙工的情況下局扶,可以允許A -> B 和 B -> A 雙向同時(shí)通訊恨统,A和B都可以接受和發(fā)送信息,就像打電話(huà)那樣三妈。
半雙工(half-duplex):
在同一個(gè)時(shí)間段內(nèi)畜埋,每次只能由一端發(fā)起通信,意思就是只能同時(shí)有一個(gè)發(fā)送端和接收端畴蒲,就像對(duì)講機(jī)那樣悠鞍。
現(xiàn)在進(jìn)入正軌,翻譯一波:
h5 webSocket 規(guī)范定義了一個(gè)讓網(wǎng)頁(yè)通過(guò)webSocket協(xié)議和一個(gè)遠(yuǎn)程主機(jī)雙向通信的API模燥。與不可縮放的輪詢(xún)和長(zhǎng)輪詢(xún)相比咖祭,他提供了一個(gè)極大減少不必要的網(wǎng)絡(luò)流量和延遲的方法,并且通過(guò)保持兩端連接而模擬出一個(gè)全雙工連接蔫骂。通信方式如下圖所示:
WebSocket提供的獨(dú)特功能之一就是它能夠穿越防火墻和代理么翰。
WebSocket檢測(cè)到代理服務(wù)器的存在,并自動(dòng)設(shè)置一個(gè)通道來(lái)通過(guò)代理服務(wù)器辽旋。隧道是通過(guò)向代理服務(wù)器發(fā)出HTTP連接語(yǔ)句來(lái)建立的浩嫌,該語(yǔ)句請(qǐng)求代理服務(wù)器打開(kāi)到特定主機(jī)和端口的TCP/IP連接。一旦建立了隧道补胚,通信就可以暢通無(wú)阻地通過(guò)代理固该。
總而言之,websocket就是一個(gè)可以保持長(zhǎng)連接糖儡,和http沒(méi)有半毛錢(qián)關(guān)系的一種新協(xié)議。在沒(méi)有這個(gè)而之前怔匣,當(dāng)我們想要獲取實(shí)時(shí)的數(shù)據(jù)握联,總不能一直發(fā)起http請(qǐng)求桦沉,一直追問(wèn)服務(wù)器有沒(méi)有數(shù)據(jù)吧,而且http是一次連接金闽,完成任務(wù)后就斷開(kāi)纯露,如果一直不斷連接斷開(kāi),就會(huì)造成不必要的網(wǎng)路流量代芜。此時(shí)埠褪,救星登場(chǎng)了,websocket只要一次連接挤庇,發(fā)送完該發(fā)的信息(具體和服務(wù)端協(xié)商)钞速,然后就開(kāi)始躺著等數(shù)據(jù),開(kāi)一個(gè)監(jiān)控嫡秕,只要服務(wù)器有數(shù)據(jù)推送過(guò)來(lái)渴语,再起來(lái)干活,這樣網(wǎng)絡(luò)通信流量的壓力就會(huì)小很多昆咽。
二驾凶、實(shí)例
拿現(xiàn)手的一個(gè)小頁(yè)面做例子:實(shí)現(xiàn)一個(gè)查看人員實(shí)時(shí)位置的地圖
當(dāng)一切布局,地圖巴拉巴拉一堆東西完成之后
(1)連接
initWebSocket () {
this.websocket = new WebSocket(
`ws://xxx:8081/webSocket/${this.userId}`
)
var that = this.websocket
that.onopen = this.websocketonopen
that.onerror = this.websocketonerror
that.onmessage = this.websocketonmessage
that.onclose = this.websocketclose
}
先創(chuàng)建一個(gè)WebSocket
對(duì)象掷酗,this.userId
是與后端協(xié)商好的调违,一個(gè)用于標(biāo)識(shí)用戶(hù)身份的。接下去就是對(duì)發(fā)送成功泻轰、發(fā)送失敗技肩、接受到服務(wù)器的數(shù)據(jù)和連接關(guān)閉的監(jiān)聽(tīng)設(shè)置。
(2)發(fā)送成功時(shí)
websocketonopen () {
console.log('WebSocket連接成功')
const data = { user_id: this.userId, group_id: 1}
this.websocket.send(JSON.stringfy(data))
}
定義websocket連接完成后糕殉,進(jìn)行的操作亩鬼,此時(shí)可以發(fā)送一些參數(shù),但是注意阿蝶,基于socket的數(shù)據(jù)發(fā)送只支持字符串或者二進(jìn)制流雳锋。
(3)發(fā)送失敗時(shí)
websocketonerror (e) {
console.log('WebSocket連接發(fā)生錯(cuò)誤')
},
(4)監(jiān)聽(tīng)數(shù)據(jù)
websocketonmessage (e) {
if (e.data !== '連接成功') {
let data = JSON.parse(e.data)
this.userArr = data
// 此處為對(duì)接收到的數(shù)據(jù)進(jìn)行的操作
// ...
} else {
this.delOverlay()
}
}
}
同樣接收到的數(shù)據(jù),也是字符串格式的羡洁,我們只要解析一下就可以了
(5)關(guān)閉連接
websocketclose (e) {
console.log('connection closed (' + e.code + ')')
},
返回一個(gè)對(duì)象玷过,有返回碼,這個(gè)操作筑煮,對(duì)于vue我們可以在destroy生命周期摧毀階段打印出來(lái)
注意:
如果遇到了websocket跨域的問(wèn)題辛蚊,可以使用socket.io庫(kù),他幫我們很好地封裝了websocket
參考文章: https://www.zhihu.com/question/20215561