目錄
一、Websocket是什么
二、Websocket的基本使用
使用介紹
第一步
第二步
第三步
第四步
常用API介紹?
WebSocket(url[, protocols])
WebSocket.readyState
?WebSocket.send(data)
WebSocket.close([code[, reason]])
WebSocket.bufferedAmount
WebSocket.extensions
WebSocket.binaryType
三、Websocket的封裝
vue代碼
react代碼
一、Websocket是什么
????????當一個Web應用程序需要實現(xiàn)實時雙向通信時,傳統(tǒng)的?HTTP?協(xié)議并不是最佳選擇,因為HTTP是一個請求/響應協(xié)議,它的工作方式是客戶端發(fā)送一個請求給服務器,服務器然后響應該請求,并發(fā)送一個響應給客戶端。這種模式通常是單向的,客戶端只能發(fā)起請求,而服務器只能響應請求。這意味著,客戶端無法在不發(fā)出新請求的情況下接收來自服務器的新數(shù)據(jù)。
????????WebSocket?協(xié)議就是為了解決這個問題而產(chǎn)生的,它可以在客戶端和服務器之間建立持久的連接,以便實現(xiàn)雙向通信。在建立連接之后,客戶端和服務器可以隨時發(fā)送消息,而不需要通過HTTP請求/響應的方式進行通信。此外,WebSocket還支持二進制數(shù)據(jù)的傳輸,這使得它更加靈活,可以用于許多不同的應用程序場景。
WebSocket協(xié)議的工作方式如下:
- 客戶端向服務器發(fā)起一個WebSocket握手請求。這個請求與HTTP請求非常相似,但包含了一些附加的頭部信息,以表示這是一個WebSocket請求。
- 服務器對該請求進行響應,包含一個狀態(tài)碼和一些頭部信息。這個響應是HTTP響應,但同樣包含了一些附加的頭部信息,以表示這是一個WebSocket響應。
- 客戶端和服務器之間的連接現(xiàn)在已經(jīng)建立,并且可以進行雙向通信了。客戶端和服務器都可以隨時發(fā)送消息,這些消息會被封裝為WebSocket幀并通過WebSocket連接進行傳輸。
????????需要注意的是,WebSocket協(xié)議與傳統(tǒng)的HTTP協(xié)議不同,因為它不是基于請求/響應模式的。這意味著,一旦連接建立,客戶端和服務器就可以隨時發(fā)送消息,而不需要等待對方先發(fā)出請求。此外,WebSocket協(xié)議還支持心跳包機制,可以檢測連接是否還處于活動狀態(tài)。
????????總之,WebSocket協(xié)議提供了一種高效、可靠、靈活的方式來實現(xiàn)Web應用程序之間的實時雙向通信。它是一個強大的工具,可以用于許多不同的應用程序場景,包括在線游戲、實時聊天、數(shù)據(jù)傳輸和多人協(xié)作等等。
二、Websocket的基本使用
使用介紹
????????前端使用WebSocket通常需要使用瀏覽器提供的WebSocket API,該API可以通過JavaScript代碼與WebSocket服務器建立連接,并在連接建立后進行數(shù)據(jù)傳輸。
第一步
????????創(chuàng)建一個WebSocket對象??梢允褂靡韵麓a創(chuàng)建一個WebSocket對象:
const socket = new WebSocket('ws://localhost:8080');
????????在創(chuàng)建WebSocket對象時,需要傳遞WebSocket服務器的地址和端口號作為參數(shù)。WebSocket服務器地址可以使用ws://
或wss://
前綴表示,ws://
表示使用普通的HTTP協(xié)議進行通信,wss://
表示使用加密的HTTP協(xié)議進行通信。
第二步
????????監(jiān)聽WebSocket事件。WebSocket API提供了幾種事件類型,可以通過這些事件來處理WebSocket的連接狀態(tài)和數(shù)據(jù)傳輸。下面是常用的事件類型:
-
open
:WebSocket連接成功時觸發(fā)。 -
message
:接收到WebSocket服務器發(fā)送的消息時觸發(fā)。 -
error
:WebSocket連接出錯時觸發(fā)。 -
close
:WebSocket連接關(guān)閉時觸發(fā)。
可以使用下面的代碼監(jiān)聽WebSocket事件:
socket.addEventListener('open', (event) => {
console.log('WebSocket連接已打開');
});
socket.addEventListener('message', (event) => {
console.log('接收到消息:', event.data);
});
socket.addEventListener('error', (event) => {
console.log('WebSocket連接出錯:', event);
});
socket.addEventListener('close', (event) => {
console.log('WebSocket連接已關(guān)閉');
});
第三步
????????發(fā)送數(shù)據(jù)。可以使用WebSocket.send()
方法向WebSocket服務器發(fā)送數(shù)據(jù)。該方法接受一個字符串或一個二進制數(shù)據(jù)對象作為參數(shù)。下面是一個例子:?
? ? ? ? 這里需要注意的是如果傳輸?shù)臄?shù)據(jù)為對象格式,應轉(zhuǎn)換為JOSN格式進行傳輸。??
socket.send('Hello, WebSocket!');
第四步
????????關(guān)閉連接??梢允褂?code>WebSocket.close()方法關(guān)閉WebSocket連接。
socket.close();
常用API介紹?
WebSocket(url[, protocols])
????????創(chuàng)建WebSocket對象。其中,url參數(shù)是WebSocket服務器的地址,protocols參數(shù)是一個可選的字符串或字符串數(shù)組,表示W(wǎng)ebSocket協(xié)議的子協(xié)議列表。(見使用介紹第一步)
WebSocket.readyState
????????WebSocket對象的只讀屬性,表示當前WebSocket的連接狀態(tài),它的值為下面四個之一:
- 0 - 表示W(wǎng)ebSocket連接尚未建立。
- 1 - 表示W(wǎng)ebSocket連接已建立,可以進行通信。
- 2 - 表示W(wǎng)ebSocket連接正在關(guān)閉。
- 3 - 表示W(wǎng)ebSocket連接已經(jīng)關(guān)閉或者連接不能打開。
console.log(this.webSocket.readyState)
?WebSocket.send(data)
????????向WebSocket服務器發(fā)送數(shù)據(jù)。其中,data參數(shù)可以是一個字符串、一個二進制數(shù)據(jù)對象或者一個Blob對象。(見使用介紹第三步)
WebSocket.close([code[, reason]])
關(guān)閉WebSocket連接。其中,code參數(shù)表示關(guān)閉代碼,reason參數(shù)表示關(guān)閉原因。(見使用介紹第四步)
WebSocket.bufferedAmount
????????WebSocket的bufferedAmount
屬性表示已經(jīng)被send()方法發(fā)送但還沒有被發(fā)送到網(wǎng)絡層的數(shù)據(jù)量。在發(fā)送數(shù)據(jù)的過程中,如果發(fā)送的數(shù)據(jù)量大于WebSocket的緩沖區(qū)大小,那么這些數(shù)據(jù)就會被暫時保存在WebSocket的緩沖區(qū)中,直到網(wǎng)絡層可以接受這些數(shù)據(jù)時再發(fā)送出去。
const socket = new WebSocket('ws://localhost:8080');
console.log('初始bufferedAmount:', socket.bufferedAmount);
socket.send('Hello, WebSocket!');
console.log('發(fā)送后bufferedAmount:', socket.bufferedAmount);
WebSocket.extensions
????????WebSocket的extensions
屬性是一個只讀屬性,它表示W(wǎng)ebSocket服務器支持的擴展列表。
const socket = new WebSocket('ws://localhost:8080');
console.log('WebSocket服務器支持的擴展:', socket.extensions);
WebSocket.binaryType
????????WebSocket的binaryType
屬性表示在收到二進制數(shù)據(jù)時使用的編碼方式,默認值是"blob"。可以將其設置為"arraybuffer"來使用ArrayBuffer對象來處理二進制數(shù)據(jù)。
const socket = new WebSocket('ws://localhost:8080');
socket.binaryType = 'arraybuffer';
socket.addEventListener('message', (event) => {
const arrayBuffer = event.data;
// 處理二進制數(shù)據(jù)
});
三、Websocket的封裝
vue代碼
import Vue from 'vue'
import { Message } from 'element-ui'
let v = new Vue()
v.$message = Message;
var webSocket = null;
var isConnect = false; //連接狀態(tài)
var globalCallback = function(e){ console.log(e) };//定義外部接收數(shù)據(jù)的回調(diào)函數(shù)
var reConnectNum = 0;//重連次數(shù)
var websocketUrl = process.env.VUE_APP_API_WEBSOCKET_URL;
//心跳設置
var heartCheck = {
heartbeatData:{
DevID:{
value:Vue.ls.get('devid')
},
DevHeart:{
value:"1"
}
},//心跳包
timeout: 60 * 1000, //每段時間發(fā)送一次心跳包 這里設置為60s
heartbeat: null, //延時發(fā)送消息對象(啟動心跳新建這個對象,收到消息后重置對象)
start: function () {
this.heartbeat = setInterval(()=>{
if (isConnect){
webSocketSend(this.heartbeatData);
}else{
this.clear();
}
}, this.timeout);
},
reset: function () {
clearInterval(this.heartbeat);
this.start();
},
clear:function(){
clearInterval(this.heartbeat);
}
}
//初始化websocket
function initWebSocket(callback) {
//此callback為在其他地方調(diào)用時定義的接收socket數(shù)據(jù)的函數(shù)
if(callback){
if(typeof callback == 'function'){
globalCallback = callback
}else{
throw new Error("callback is not a function")
}
}
if ("WebSocket" in window) {
webSocket = new WebSocket(websocketUrl);//創(chuàng)建socket對象
} else {
Message({
message: '該瀏覽器不支持websocket!',
type: 'warning'
});
return
}
//打開
webSocket.onopen = function() {
webSocketOpen();
};
//收信
webSocket.onmessage = function(e) {
webSocketOnMessage(e);
};
//關(guān)閉
webSocket.onclose = function(e) {
webSocketOnClose(e);
};
//連接發(fā)生錯誤的回調(diào)方法
webSocket.onerror = function(e) {
webSocketonError(e);
};
}
//連接socket建立時觸發(fā)
function webSocketOpen() {
console.log("WebSocket連接成功");
//首次握手
webSocketSend(heartCheck.heartbeatData);
isConnect = true;
heartCheck.start();
reConnectNum = 0;
}
//客戶端接收服務端數(shù)據(jù)時觸發(fā),e為接受的數(shù)據(jù)對象
function webSocketOnMessage(e) {
console.log("websocket信息:");
console.log(e.data)
const data = JSON.parse(e.data);//根據(jù)自己的需要對接收到的數(shù)據(jù)進行格式化
globalCallback(data);//將data傳給在外定義的接收數(shù)據(jù)的函數(shù),至關(guān)重要。
}
//socket關(guān)閉時觸發(fā)
function webSocketOnClose(e){
heartCheck.clear();
isConnect = false; //斷開后修改標識
console.log(e)
console.log('webSocket已經(jīng)關(guān)閉 (code:' + e.code + ')')
//被動斷開,重新連接
if(e.code == 1006){
if(reConnectNum < 3){
initWebSocket();
++reConnectNum;
}else{
v.$message({
message: 'websocket連接不上,請刷新頁面或聯(lián)系開發(fā)人員!',
type: 'warning'
});
}
}
}
//連接發(fā)生錯誤的回調(diào)方法
function webSocketonError(e){
heartCheck.clear();
isConnect = false; //斷開后修改標識
console.log("WebSocket連接發(fā)生錯誤:");
console.log(e);
}
//發(fā)送數(shù)據(jù)
function webSocketSend(data) {
webSocket.send(JSON.stringify(data));//在這里根據(jù)自己的需要轉(zhuǎn)換數(shù)據(jù)格式
}
//在其他需要socket地方主動關(guān)閉socket
function closeWebSocket(e) {
webSocket.close();
heartCheck.clear();
isConnect = false;
reConnectNum = 0;
}
//在其他需要socket地方接受數(shù)據(jù)
function getSock(callback) {
globalCallback = callback
}
//在其他需要socket地方調(diào)用的函數(shù),用來發(fā)送數(shù)據(jù)及接受數(shù)據(jù)
function sendSock(agentData) {
//下面的判斷主要是考慮到socket連接可能中斷或者其他的因素,可以重新發(fā)送此條消息。
switch (webSocket.readyState) {
//CONNECTING:值為0,表示正在連接。
case webSocket.CONNECTING:
setTimeout(function() {
sendSock(agentData, callback);
}, 1000);
break;
//OPEN:值為1,表示連接成功,可以通信了。
case webSocket.OPEN:
webSocketSend(agentData);
break;
//CLOSING:值為2,表示連接正在關(guān)閉。
case webSocket.CLOSING:
setTimeout(function() {
sendSock(agentData, callback);
}, 1000);
break;
//CLOSED:值為3,表示連接已經(jīng)關(guān)閉,或者打開連接失敗。
case webSocket.CLOSED:
// do something
break;
default:
// this never happens
break;
}
}
export default {
initWebSocket,
closeWebSocket,
sendSock,
getSock
};
vue方法來自于這位大佬的文章,以下是鏈接。websocket封裝_Paul_Chan_的博客-CSDN博客websocket封裝https://blog.csdn.net/weixin_43422861/article/details/114259139?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168336616716782425125574%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=168336616716782425125574&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-1-114259139-null-null.142%5Ev86%5Einsert_down28,239%5Ev2%5Einsert_chatgpt&utm_term=websocket%E5%B7%A5%E5%85%B7%E5%B0%81%E8%A3%85&spm=1018.2226.3001.4187
react代碼
import React, { Component } from 'react';
class WebSocketHelper extends Component {
constructor(props) {
super(props);
this.state = {
websocket: null,
heartBeatIntervalId: null,
};
}
componentDidMount() {
this.connectWebSocket();
}
componentWillUnmount() {
this.closeWebSocket();
}
connectWebSocket = () => {
const websocket = new WebSocket(this.props.url);
websocket.onopen = () => {
console.log('WebSocket connection opened.');
this.props.onOpen && this.props.onOpen();
if (this.props.heartBeatInterval) {
const heartBeatIntervalId = setInterval(() => {
console.log('Sending WebSocket heartbeat.');
this.sendMessage(this.props.heartBeatMessage);
}, this.props.heartBeatInterval);
this.setState({ heartBeatIntervalId });
}
};
websocket.onclose = () => {
console.log('WebSocket connection closed.');
this.props.onClose && this.props.onClose();
if (this.state.heartBeatIntervalId) {
clearInterval(this.state.heartBeatIntervalId);
this.setState({ heartBeatIntervalId: null });
}
setTimeout(() => {
console.log('Attempting to reconnect WebSocket.');
this.connectWebSocket();
}, this.props.reconnectInterval || 5000);
};
websocket.onerror = (error) => {
console.error('WebSocket error:', error);
this.props.onError && this.props.onError(error);
};
websocket.onmessage = (event) => {
console.log('WebSocket message received:', event.data);
this.props.onMessage && this.props.onMessage(event.data);
};
this.setState({ websocket });
}
closeWebSocket = () => {
if (this.state.websocket) {
this.state.websocket.close();
console.log('WebSocket connection closed.');
if (this.state.heartBeatIntervalId) {
clearInterval(this.state.heartBeatIntervalId);
this.setState({ heartBeatIntervalId: null });
}
}
}
sendMessage = (message) => {
if (this.state.websocket) {
console.log('Sending WebSocket message:', message);
this.state.websocket.send(message);
}
}
render() {
return this.props.render({
sendMessage: this.sendMessage,
closeWebSocket: this.closeWebSocket,
});
}
}
export default WebSocketHelper;
使用文章來源:http://www.zghlxwxcb.cn/news/detail-435507.html
import React from 'react';
import WebSocketHelper from './WebSocketHelper';
function App() {
const handleOpen = () => {
console.log('WebSocket connection opened.');
};
const handleClose = () => {
console.log('WebSocket connection closed.');
};
const handleError = (error) => {
console.error('WebSocket error:', error);
};
const handleMessage = (message) => {
console.log('WebSocket message received:', message);
};
const handleRender = ({ sendMessage, closeWebSocket }) => {
// 這里可以使用 sendMessage 和 closeWebSocket 方法
return (
<div>
<button onClick={() => sendMessage('Hello WebSocket!')}>Send Message</button>
<button onClick={() => closeWebSocket()}>Close WebSocket</button>
</div>
);
};
return (
<WebSocketHelper
url="wss://example.com"
onOpen={handleOpen}
onClose={handleClose}
onError={handleError}
onMessage={handleMessage}
render={handleRender}
/>
);
}
export default App;
? ? ? ? ? ?更多詳細信息詳見官網(wǎng):https://www.websocket.org/https://www.websocket.org/文章來源地址http://www.zghlxwxcb.cn/news/detail-435507.html
到了這里,關(guān)于Websocket的基本認識、使用與封裝的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!