84 lines
2.3 KiB
JavaScript
84 lines
2.3 KiB
JavaScript
const WebSocket = require("ws");
|
|
|
|
// 创建 WebSocket 服务器实例
|
|
const wss = new WebSocket.Server({ port: 8080 });
|
|
|
|
// 客户端超时时间(与服务端要求的 5 秒一致)
|
|
const CLIENT_TIMEOUT = 10000; // 5 秒
|
|
|
|
// 客户端连接池(用于记录所有活跃连接)
|
|
const clients = new Map();
|
|
|
|
wss.on("connection", (ws) => {
|
|
console.log("新客户端连接");
|
|
|
|
// 初始化客户端心跳检测
|
|
let timeoutTimer = null;
|
|
|
|
// 为每个客户端创建唯一标识(可以用其他方式生成)
|
|
const clientId = Date.now().toString();
|
|
clients.set(clientId, ws);
|
|
|
|
// 心跳检测方法
|
|
const heartbeat = () => {
|
|
// 每次收到消息时重置定时器
|
|
if (timeoutTimer) clearTimeout(timeoutTimer);
|
|
// 设置新的超时检测
|
|
timeoutTimer = setTimeout(() => {
|
|
console.log(`客户端 ${clientId} 心跳超时,关闭连接`);
|
|
// ws.close(); // 主动关闭连接
|
|
clients.delete(clientId); // 从连接池移除
|
|
}, CLIENT_TIMEOUT);
|
|
};
|
|
|
|
// 初始检测
|
|
heartbeat();
|
|
|
|
// 收到消息时触发
|
|
ws.on("message", (message) => {
|
|
console.log(`收到来自 ${clientId} 的消息: ${message}`);
|
|
|
|
// 重置心跳检测
|
|
heartbeat();
|
|
|
|
// // 如果需要响应心跳(示例代码)
|
|
// if (message === "heartbeat") {
|
|
// ws.send("heartbeat-ack"); // 发送心跳确认
|
|
// }
|
|
});
|
|
|
|
// 连接关闭时触发
|
|
ws.on("close", () => {
|
|
console.log(`客户端 ${clientId} 连接关闭`);
|
|
if (timeoutTimer) clearTimeout(timeoutTimer);
|
|
clients.delete(clientId); // 清理连接池
|
|
});
|
|
|
|
// 连接错误时触发
|
|
ws.on("error", (error) => {
|
|
console.error(`客户端 ${clientId} 发生错误:`, error);
|
|
if (timeoutTimer) clearTimeout(timeoutTimer);
|
|
clients.delete(clientId); // 清理连接池
|
|
});
|
|
});
|
|
|
|
console.log("WebSocket 服务端已启动,监听端口 8080");
|
|
|
|
// 示例:当客户端超时时,可以执行自定义逻辑
|
|
function onClientTimeout(clientId) {
|
|
console.log(`[自定义处理] 客户端 ${clientId} 已断开`);
|
|
// 这里可以添加你的业务逻辑,例如:
|
|
// 1. 通知其他客户端
|
|
// 2. 更新数据库状态
|
|
// 3. 触发重新连接等
|
|
}
|
|
|
|
// 服务器关闭时的清理
|
|
process.on("SIGINT", () => {
|
|
console.log("\n正在关闭服务器...");
|
|
wss.close(() => {
|
|
console.log("服务器已关闭");
|
|
process.exit();
|
|
});
|
|
});
|