什么是 WebSocket
WebSocket 是 HTML5 中的协议,支持持久连续,HTTP 协议不支持持久性连接。HTTP1.0 和 HTTP1.1 都不支持持久性的链接,HTTP1.1 中 的keep-alive,是将多个 HTTP 请求合并为 1 个
websocket 方法
- open
- close
- error
- message
- connection 【后端的】
思路
- 前端:
const ws = new WebSocket('ws:localhost:8000')
- 监听 ws 事件:
ws.addEventListener('open', handleOpen, false);
ws.addEventListener('close', handleClose, false);
ws.addEventListener('error', handleClose, false);
ws.addEventListener('message', handleMessage, false);
handleMessage(e) { const msgData = JSON.prase(e.data) }
- 发送消息:
ws.send(JSON.stringify({}));
- 后端:
const Ws = require('ws');
const server = new Ws.Server({ port: 8000 })
- 监听事件:
server.on('open', handleOpen);
server.on('close', handleClose);
server.on('error', handleError);
server.on('connection', handleConnection);
前端连接上来后:handleConnection(ws) { ws.on('message', handleMessage) }
- 监听 message 事件,再通过 clients 广播给所有客户端
handleMessage(data, isBinary) { server.clients.forEach(c => c.send(data, { binary: isBinary }) ) }
前端
- entry.html 入口页
- input 输入用户名
- btn 进入聊天室
- index.html 聊天室
- list 聊天列表
- input 聊天框
- btn 发送 message
- open
- close
- error
- message
npm install vite
package.json:
"scripts": {
"dev": "vite"
},
后端
- open
- close
- error
- message
- connection
依赖一个库:
- ws
或者用原生的:
- nodejs-websocket
心跳
核心思路
- 每隔一段固定的时间,向服务器端发送一个ping数据,如果在正常的情况下,服务器会返回一个pong给客户端
- 如果客户端通过 onmessage 事件能监听到的话,说明请求正常
- 这里我们使用了一个定时器,每隔3秒的情况下,如果是网络断开的情况下,在指定的时间内服务器端并没有返回心跳响应消息,因此服务器端断开了,
- 因此这个时候我们使用ws.close关闭连接,在一段时间后(在不同的浏览器下,时间是不一样的,firefox响应更快),可以通过 onclose 事件监听到。
- 因此在onclose事件内,我们可以调用 reconnect事件进行重连操作。
<html>
<head>
<meta charset="utf-8">
<title>WebSocket Demo</title>
</head>
<body>
<script type="text/javascript">
// var ws = new WebSocket("wss://echo.websocket.org");
/*
ws.onerror = function(e) {
console.log('已关闭');
};
ws.onopen = function(e) {
console.log('握手成功');
ws.send('123456789');
}
ws.onclose = function() {
console.log('已关闭');
}
ws.onmessage = function(e) {
console.log('收到消息');
console.log(e);
}
*/
var lockReconnect = false;//避免重复连接
var wsUrl = "wss://echo.websocket.org";
var ws;
var tt;
function createWebSocket() {
try {
ws = new WebSocket(wsUrl);
init();
} catch(e) {
console.log('catch');
reconnect(wsUrl);
}
}
function init() {
ws.onclose = function () {
console.log('链接关闭');
reconnect(wsUrl);
};
ws.onerror = function() {
console.log('发生异常了');
reconnect(wsUrl);
};
ws.onopen = function () {
//心跳检测重置
heartCheck.start();
};
ws.onmessage = function (event) {
//拿到任何消息都说明当前连接是正常的
console.log('接收到消息');
heartCheck.start();
}
}
function reconnect(url) {
if(lockReconnect) {
return;
};
lockReconnect = true;
//没连接上会一直重连,设置延迟避免请求过多
tt && clearTimeout(tt);
tt = setTimeout(function () {
createWebSocket(url);
lockReconnect = false;
}, 4000);
}
//心跳检测
var heartCheck = {
timeout: 3000,
timeoutObj: null,
serverTimeoutObj: null,
start: function(){
console.log('start');
var self = this;
this.timeoutObj && clearTimeout(this.timeoutObj);
this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
this.timeoutObj = setTimeout(function(){
//这里发送一个心跳,后端收到后,返回一个心跳消息,
console.log('55555');
ws.send("123456789");
self.serverTimeoutObj = setTimeout(function() {
console.log(111);
console.log(ws);
ws.close();
// createWebSocket();
}, self.timeout);
}, this.timeout)
}
}
createWebSocket(wsUrl);
</script>
</body>
</html>
Comments NOTHING