WebSocket基本介紹
WebSocket 是 HTML5 開始提供的一種在單個 TCP 連接上進行全雙工通訊的協(xié)議。
WebSocket 使得客戶端和服務器之間的數(shù)據(jù)交換變得更加簡單,允許服務端主動向客戶端推送數(shù)據(jù)。在 WebSocket API 中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進行雙向數(shù)據(jù)傳輸。
在 WebSocket API 中,瀏覽器和服務器只需要做一個握手的動作,然后,瀏覽器和服務器之間就形成了一條快速通道。兩者之間就直接可以數(shù)據(jù)互相傳送。
瀏覽器通過 JavaScript 向服務器發(fā)出建立 WebSocket 連接的請求,連接建立以后,客戶端和服務器端就可以通過 TCP 連接直接交換數(shù)據(jù)。
WebSocket 狀態(tài)
在上面代碼中我們通過WebSocket()
構(gòu)造函數(shù)來構(gòu)造一個ws
實例。對應的這個實例中有只讀屬性 readyState 表示連接狀態(tài)四個狀態(tài),對應的分別有四個不同的值,具體如下:
狀態(tài) | 值 | 說明 |
---|---|---|
WebSocket.CONNECTING | 0 | 表示連接尚未建立 |
WebSocket.OPEN | 1 | 表示連接已建立,可以進行通信 |
WebSocket.CLOSING | 2 | 表示連接正在進行關閉 |
WebSocket.CLOSED | 3 | 表示連接已經(jīng)關閉或者連接不能打開 |
WebSocket 事件
整個ws
建立的過程有四個比較重要的事件,分別是:
- open階段:WebSocket.onopen屬性定義一個事件處理程序,當WebSocket 的連接狀態(tài)readyState 變?yōu)?時調(diào)用;這意味著當前連接已經(jīng)準備好發(fā)送和接受數(shù)據(jù)。這個事件處理程序通過 事件(建立連接時)觸發(fā)
- message:message 事件會在 WebSocket 接收到新消息時被觸發(fā)
- close:WebSocket.onclose 屬性返回一個事件監(jiān)聽器,這個事件監(jiān)聽器將在 WebSocket 連接的readyState 變?yōu)?CLOSED時被調(diào)用,它接收一個名字為“close”的 CloseEvent 事件
- error:當websocket的連接由于一些錯誤事件的發(fā)生 (例如無法發(fā)送一些數(shù)據(jù)) 而被關閉時,一個error事件將被引發(fā)
WebSocket 方法
在ws
中我們常用的有如下兩個方法:
- send:使用連接發(fā)送數(shù)據(jù)
- close:關閉連接
HTML中建立ws
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>websocket-demo</title>
</head>
<body>
</body>
<script>
// 建立ws連接
const wbSocket = () => {
// ws實例
let webSocket = null;
// 檢測心跳的間隔ID
let intervalID = null;
const connect = async () => {
// 服務端ws的地址
const wsUrl = 'ws://10.199.161.17:9010/ws?deviceId=A51a007F-0620-467B-8A4a-c8a6c9aD69FD&protocolVersion=3'
// https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
// CLOSED
if (webSocket && webSocket.readyState !== 3) {
return;
}
// Create WebSocket connection.
webSocket = new WebSocket(wsUrl);
// 連接已經(jīng)準備好發(fā)送和接受數(shù)據(jù)
webSocket.addEventListener("open", (event) => {
webSocket.send("Hello Server, connection has build", event);
});
// Listen for messages
webSocket.addEventListener("message", async (event) => {
console.log("Message from server: ", event.data);
const receivedData = event.data;
if (receivedData instanceof Blob) {
try {
const buffer = await event.data.arrayBuffer()
// 建立DateView對象來讀寫緩沖區(qū) 按照有符號的8位數(shù)字讀取
const view = new Int8Array(buffer);
// 將類數(shù)組view轉(zhuǎn)化為數(shù)組,方便讀取
const list = Array.from(view)
console.log(list);
} catch (error) {
console.log('解析blob出錯', error.message);
}
} else {
console.log('接受到的數(shù)據(jù)');
}
});
// Listen for possible errors
webSocket.addEventListener("error", (event) => {
console.log("WebSocket error: ", event);
});
webSocket.addEventListener("close", event => {
console.log("socket closed ", event.data);
// 將webSocket 設為Null, 不再發(fā)送心跳 等待重新建立連接
clearInterval(intervalID)
webSocket = null;
intervalID = null;
});
}
setInterval(() => {
// 如果有socket實例并且有心跳就直接返回
if (webSocket && webSocket) return
// 無ws實力 or 心跳id則建立ws連接
connect()
}, 5 * 1000)
}
wbSocket()
</script>
</html>
可以看到在上面代碼中我們對服務端返回給前端的值做了一層判定,有時服務端在特定的場景下會使用java中的netty這個工具包返回給前端的數(shù)據(jù)是二進制的,就需要前端判斷之后自己再使用arrayBuffer
這個API自己轉(zhuǎn)一下。
如果服務端此時返回的是一個正常的數(shù)據(jù)而非Blob
的話,那就可以直接在event.data
中獲取就可以了。
需要注意一點是ArrayBuffer
是一個表示原始二進制數(shù)據(jù)的緩沖區(qū),是一個字節(jié)數(shù)組,并不能直接操作ArrayBuffer
中的內(nèi)容。需要通過DataView
對象來操作
瀏覽器中查看ws
如果打印出上面代碼中的buffer
的話console.log(111, buffer);
會在瀏覽器如下顯示:
我們點擊右側(cè)的那個點之后,會跳轉(zhuǎn)到瀏覽器的內(nèi)存檢查器,查看對應的值以及存這些值的地址。文章來源:http://www.zghlxwxcb.cn/news/detail-609674.html
參考資料
WebSocket
HTML5 WebSocket
ArrayBuffer文章來源地址http://www.zghlxwxcb.cn/news/detail-609674.html
到了這里,關于HTML5 WebSocket介紹與基本使用(解析服務端返回的二進制數(shù)據(jù))的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!