小工具知识网

当前位置: 首页 > 行业知识 > 前端面试练习24.3.6

行业知识

前端面试练习24.3.6

2026-11-08 19:04:43 来源:互联网转载

前言:

今天就���复习回顾一下websocket,之前有个AI项目使用到了这个,有点久远了,回顾一下大致过程和难点。

()

一些知识点:

1.单工,半双工,全双工

单工:

数据只能沿着一个方向传递,例如电视广播等。

优点:实现简单

缺点:传输效率低

半双工:

数据可以在双方之间进行传递,但是不能同时进行,必须有个 发送/接收 角色的转换,一方发送完成另一方才能发送。比如对讲机。

全双工:

数据可以同时在两个方向上传输,通信的两个设备之间可以同时的收发消息,无需等待对方完成,极大地提高了数据的传输效率,典型用例就是电话。

2.websocket可能遇到的难点

参考WebSocket项目中难点与解决方法_websocket客服聊天 难点-CSDN博客

难点一:连接的建立与保持

1.采用连接池

WebSocket初始连接负担较大,主要体现在频繁的连接建立和保持连接的开销较高。

采用连接池,服务端解决

引入了websocket-pool库,通过维护连接池,成功实现了连接的复用。这极大地降低了频繁建立和关闭连接的开销,提升了性能。

 

2.心跳机制引入

 实施了定时的心跳机制,周期性地向服务器发送心跳消息,确保连接保持活跃。这有效防止了连接被自动关闭,提高了连接的可靠性。

3.长连接,适当延长连接时常

比如在连接时,设置超时时长5秒,5秒内没有得到服务器回应,则出现超时提示​​​​​​​

  

难点二:错误处理与断线重连

1.错误处理

 监听onerror事件,当 WebSocket 发生错误时,执行回调函数捕获错误信息​​​​​​​

2.短线重连

 自动断线重连机制,采用了指数退避算法。通过逐渐增加重连的间隔时间,我们成功避免了频繁尝试重新建立连接,确保了连接的稳定性和用户体验。

难点三:性能的一些优化

1.消息压缩

目前还没解决

2.并发限制

连接池设置最大数量

3.消息队列

目前没解决

websocket实战:

服务端创建websocket服务

创建node项目,安装相关依赖

npm init -ynpm install expressnpm install ws
const WebSocket = require('ws');const PORT = 8080;const URL = 'ws://127.0.0.1:8080';const wss = new WebSocket.Server({ port: PORT });const clients = new Map();wss.on('connection', function connection(ws) {  console.log('Client connected');  ws.on('message', function incoming(message) {    const data = JSON.parse(message);    if (typeof data !== 'string') {            let targetUser = data.toUser      // 如果客户端之前没有存储在 clients Map 中,则存储客户端连接      if (!clients.has(data.user)) {        clients.set(data.user, ws);      }      console.log(clients.keys())      // 将格式化后的消息发送给客户端      const formattedMessage = `${data.user}:  - ${data.time}
${data.message}`; if (clients.has(targetUser)) { ws.send(formattedMessage); const clientSocket = clients.get(targetUser); // 检查连接是否已经打开 if (clientSocket.readyState === WebSocket.OPEN) { // 发送消息给目标用户 clientSocket.send(formattedMessage); } else { clientSocket.send(`连接到用户 ${targetUser} 的WebSocket已关闭。`); } } else { ws.send(`用户 ${targetUser} 不在线或未连接到WebSocket服务器。`); } console.log('Received:', formattedMessage); } }); // 当完成后释放连接回连接池 // webSocketPool.releaseConnection(connection);});console.log('WebSocket server is running on port 8080');console.log(`WebSocket 服务器正在监听 127.0.0.1:${PORT}`);

客户端编写连接代码

    前端学习      * {      margin: 0px;      padding: 0px;    }    写一个聊天显示的窗口,以及信息发送输入框和发送按钮                    

WebSocket1 user:

Send

WebSocket2 user:

Send let data = [ { user: 'xhc', message: '', time: '', toUser: '' }, { user: 'slj', message: '', time: '', toUser: '' }, { user: 'aaa', message: '', time: '', toUser: '' } ] let mess1 = document.getElementById('user1_messages'); let mess2 = document.getElementById('user2_messages'); let user1_h1 = document.getElementById('user1_h1'); user1_h1.innerHTML = `${data[0].user}` let input1 = document.getElementById('messageInput1'); let input2 = document.getElementById('messageInput2'); let user2_h1 = document.getElementById('user2_h1'); user2_h1.innerHTML = `${data[1].user}` let send1 = document.getElementById('sendButton1'); let send2 = document.getElementById('sendButton2'); const URL = 'ws://localhost:8080' const connect1 = () => { // 创建 WebSocket 连接 const socket = new WebSocket(URL); let timer; // Variable to store the interval // 当连接打开时执行的操作 socket.onopen = function (event) { console.log('WebSocket1 连接已建立'); data[0].message = input1.value; data[0].time = new Date().toLocaleString(); data[0].toUser = 'slj'; // 发送消息到服务器 socket.send(JSON.stringify(data[0])); input1.value = ''; // 设置定时器,每隔30秒执行一次指定的回调函数 timer = setInterval(() => { // 检查 WebSocket 连接的当前状态是否为 OPEN if (socket.readyState === WebSocket.OPEN) { // 如果连接处于 OPEN 状态,则通过连接对象发送心跳消息 'keep-alive' socket.send(JSON.parse('keep-alive')); } }, 30000); // 每 30 秒发送一次心跳 }; // 当接收到消息时执行的操作 socket.onmessage = function (event) { let reply = event.data; mess1.innerHTML = `${mess1.innerHTML}
${reply}`; console.log('来自服务器的消息1:', reply); }; // 当连接关闭时执行的操作 socket.onclose = function (event) { mess1.innerHTML = 'WebSocket1 连接已关闭'; console.log('WebSocket1 连接已关闭'); // 清除定时器 clearInterval(timer); }; }; send1.addEventListener('click', connect1) let reconnectDelay = 2000; // 初始重连延迟为 2 秒 let reconnectCount = 0; // 当前重连次数 const maxReconnectCount = 7; // 最大重连次数为 7 const maxReconnectDelay = 60000; // 最大重连延迟为 60 秒 const connect2 = () => { let socket; // WebSocket 连接对象 let timer; // 用于心跳的定时器 let timeoutTimer; // 连接超时的定时器 // 定义超时操作函数 function handleTimeout() { console.error('WebSocket2 连接超时'); // 关闭连接 if (socket) { socket.close(); } } // 定义重新连接函数 function reconnect() { reconnectCount++; console.log(`尝试重新连接 WebSocket2,第 ${reconnectCount} 次...`); clearTimeout(timeoutTimer); // 清除超时计时器 if (reconnectCount { // 检查 WebSocket 连接的当前状态是否为 OPEN if (socket.readyState === WebSocket.OPEN) { // 如果连接处于 OPEN 状态,则通过连接对象发送心跳消息 'keep-alive' socket.send(JSON.parse('keep-alive')); } }, 30000); // 每 30 秒发送一次心跳 // 设置超时计时器 timeoutTimer = setTimeout(handleTimeout, reconnectDelay); }; // 当接收到消息时执行的操作 socket.onmessage = function (event) { mess2.innerHTML = `${mess2.innerHTML}
${event.data}`; console.log('来自服务器的消息2:', event.data); // 清除超时计时器 clearTimeout(timeoutTimer); }; // 当连接关闭时执行的操作 socket.onclose = function (event) { mess2.innerHTML = 'WebSocket2 连接已关闭'; console.log('WebSocket2 连接已关闭'); // 清除定时器 if (timer) { clearInterval(timer); } }; // 当发生错误时执行的操作 socket.onerror = function (error) { console.error('WebSocket2 连接发生错误:', error); // 清除超时计时器 clearTimeout(timeoutTimer); clearInterval(timer); }; }; send2.addEventListener('click', connect2)

上一篇:战地怎么换回橘子服务器?

下一篇:轻松掌握软件下载方法与技巧,多地下载软件攻略大解析