我們先看一下下面這張圖:

可以看到這是一個簡易的聊天室,兩個視窗的訊息是實時發送與接收的,這個主要就是用我們今天要講的websocket實作的,
websocket是什么?
websocket是一種網路通信協議,我們都知道http協議,http協議只能從客戶端主動發起,不能從服務端推送資料到客戶端,今天我們講的websocket就是一種不僅能從客戶端發送資料到服務端,也可以主動從服務的推送資料給客戶端的一種協議,
我們先看一張圖:

我們可以看到,http請求是客戶端發起請求,服務端回應,然后斷開連接,客戶端發起,服務端回應的一種回圈,而websocket協議是客戶端發起連接后,就會一直保持連接,期間客戶端和服務端都可以向對方發送資料,直到連接關閉,
websocket其他的一些特點:
(1)建立在 TCP 協議之上,服務器端的實作比較容易,
(2)與 HTTP 協議有著良好的兼容性,默認埠也是80和443,并且握手階段采用 HTTP 協議,因此握手時不容易屏蔽,能通過各種 HTTP 代理服務器,
(3)資料格式比較輕量,性能開銷小,通信高效,
(4)可以發送文本,也可以發送二進制資料,
(5)沒有同源限制,客戶端可以與任意服務器通信,
(6)協議識別符號是
ws(如果加密,則為wss),服務器網址就是 URL,
應用場景
試想一下這樣的場景,我們需要實作一個支付成功后,向用戶給一個成功的提示,那么在websocket協議沒有應用之前,人們是使用一種輪詢的方式,就是客戶端定時向服務端發送請求,看有沒有收到支付金額,沒有就一直發送,收到了再停止,類似下面的代碼:
function getIsPaySuccess() {
var timmer = setInterval(function () {
$.ajax({
url: '/getJayStatus',
success: function (res) {
if (res.status) {
clearInterval(timmer)
}
},
fail: function () {
}
})
}, 1000)
}
在發送請求的工程中,浪費了大量的資源,而且回應也不是及時的,因為我是每隔1秒請求一次,并不能立刻得到支付成功的狀態,這時候我們就需要用到websocket的方式了,總體來說,websocket需要用在一些能及時回應的場景中,
1. 社交訂閱
有時候我們需要及時收到訂閱訊息,比如說開獎通知,比如說在線邀請,支付結果等,
2. 多玩家游戲
很多游戲都是協同作戰的,玩家的操作和狀態肯定需要及時同步到所有玩家,
3. 協同編輯檔案
同一份檔案,編輯狀態得同步到所有參與的用戶界面上,
4. 資料流狀態
比如說上傳下載檔案,檔案進度,檔案是否上傳成功,
5. 多人聊天
很多場景下都需要多人參與討論聊天,用戶發送的訊息得第一時間同步到所有用戶,
6. 股票虛擬貨幣價格
股票和虛擬貨幣的價格都是實時波動的,價格跟用戶的操作息息相關,及時推送對用戶跟盤有很大的幫助,
代碼實作
我們用下面一段代碼來講解websocket的創建,擁有的屬性,能呼叫的方法和能監聽的事件:
// 連接狀態的列舉
const readyStateMap = {
0: '連接尚未建立',
1: '連接已建立,可以進行通信',
2: '連接正在進行關閉',
3: '連接已經關倍訓者連接不能打開'
}
Object.freeze(readyStateMap)
class WsTest {
constructor(url) {
// 創建websocket實體,第一個引數是連接的url,沒有跨域限制,第二個引數是可接受的協議
this.ws = new WebSocket(url);
// readyState屬性,只讀屬性,表示連接狀態
console.log(this.ws.readyState, readyStateMap[this.ws.readyState])
// 只讀屬性 bufferedAmount 已被 send() 放入正在佇列中等待傳輸,但是還沒有發出的 UTF-8 文本位元組數,
console.log(this.ws.bufferedAmount)
this.initWs()
}
initWs() {
// 事件onopen,指連接成功
this.ws.onopen = () => {
console.log(this.ws.readyState, readyStateMap[this.ws.readyState])
// 方法,向服務端發送訊息,傳輸字串
this.ws.send(JSON.stringify({type: 'connection'}))
};
// 事件onmessage,指接收到服務端訊息
this.ws.onmessage = (evt) => {
console.log(evt.data, 'data')
const {type, msg} = JSON.parse(evt.data);
console.log('訊息型別:' + type, '用戶id:' + msg)
// 方法,關閉連接
this.ws.close()
console.log(this.ws.readyState, readyStateMap[this.ws.readyState])
};
// 事件onclose,關閉連接,也可以從服務端強制斷開連接,這里可以重新發起連接
this.ws.onclose = () => {
console.log(this.ws.readyState, readyStateMap[this.ws.readyState])
};
// 事件onerror,通信發生錯誤時觸發
this.ws.onerror = () => {
console.log(this.ws.readyState, readyStateMap[this.ws.readyState])
};
}
}
const ws = new WsTest('ws://203.195.156.57:30002')
上面的代碼都有注釋,應該不難看出websocket的使用方法,這段代碼可以直接放到chrome控制臺運行:

兼容性

可以看到幾乎所有瀏覽器都支持了,
總結
- websocket是一個類似http的一種通訊協議,
- websocket最大的特點是客戶端和服務端能相互給對方發送訊息,
- websocket廣泛參考在需要實時通訊的一些應用上面,
- websocket沒有同源限制,而且性能開銷小,通信高效,
本文主要講了websocket協議的定義和基本用法,下一期我會結合本文開始的聊天室來實作一個具體的websocket應用,
聊天室在線體驗地址:關注公眾號:程式零世界 體驗在線聊天
學習如逆水行舟,不進則退,前端技術飛速發展,如果每天不堅持學習,就會跟不上,我會陪著大家,每天堅持推送博文,跟大家一同進步,希望大家能關注我,第一時間收到最新文章,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/170348.html
標籤:Java
上一篇:模擬的草地
