1. WebSocket (最主流)原理它是 HTML5 的协议。首先通过 HTTP 进行一次“握手”然后升级协议为ws加密为wss。一旦连接建立就像打长途电话双方可以随时说话不用再挂断重拨。优势全双工、延迟极低。2. SSE (Server-Sent Events)原理单向通道。服务器可以不断地往前端发流数据。优势实现简单自动重连适合像ChatGPT那样的打字机效果。3. 长轮询 (Polling) 总结Vue3 实时会话 Socket.io (或 MQTT.js) Composition API (Hooks) 后端 Node.js/Java 支那这个socket.io要是发送图片呢emo表情呢还有的话是文档excel之类的呢还有的心跳检测 消息去重与有序性鉴权在 query 或者是 auth 参数到底怎么写呢哈哈哈。。。原理前端每隔 1 秒问一次“有消息吗”。现状已经过时浪费流量和性能除非要兼容极老旧的浏览器。框架名称特点适用场景Socket.io王者级别。自带断线重连、心跳检测、房间管理。复杂的 IM 聊天室、协同办公。Vue-Socket.io-Extended专门为 Vue 封装的插件支持 Vue3 和 Pinia/Vuex。Vue3 项目快速集成。MQTT.js基于发布/订阅模式。物联网 (IoT)、 ThingLinks 这种项目必备。GoEasy国内商业服务极其稳定三行代码上线。懒人福音不想折腾后端服务器的首选。在 Vue3 中我们通常把 WebSocket 逻辑封装在一个Hook里方便多个页面复用。1. 安装依赖Bashnpm install socket.io-client2. 封装useSocket.tsTypeScriptimport { ref, onUnmounted } from vue; import { io, Socket } from socket.io-client; export function useSocket(url: String) { const socket io(url); const messages ref([]); const isConnected ref(false); // 监听连接 socket.on(connect, () { isConnected.value true; console.log(连接成功:, socket.id); }); // 监听服务端发来的消息 socket.on(chat_message, (msg) { messages.value.push(msg); }); // 发送消息的方法 const sendMessage (text: string) { socket.emit(chat_message, { text, time: new Date() }); }; // 组件卸载时断开连接防止内存泄漏 onUnmounted(() { socket.disconnect(); }); return { messages, isConnected, sendMessage }; }3. 页面使用HTMLtemplate div classchat-container p v-if!isConnected正在连接服务器.../p div v-for(item, index) in messages :keyindex {{ item.text }} /div input v-modelinputMsg keyup.enterhandleSend / button clickhandleSend发送/button /div /template script setup import { ref } from vue; import { useSocket } from /hooks/useSocket; const inputMsg ref(); const { messages, isConnected, sendMessage } useSocket(http://localhost:3000); const handleSend () { if (inputMsg.value) { sendMessage(inputMsg.value); inputMsg.value ; } }; /script心跳检测 (Heartbeat)必须每隔一段时间如 30 秒发个“乒乓包”确认对方还活着否则连接会被运营商强行掐断。消息去重与有序性在高并发下消息可能会乱序前端需要根据msgId或timestamp进行排序。安全性WebSocket 也要鉴权建立连接时记得在query或者是auth参数里带上你的Token。在 Socket.io 中发送复杂内容本质上只有两种路径“发文件流”或“发 URL 地址”。1. 发送图片与文档主流推荐URL 模式不要直接把几 MB 的图片或 Excel 转成 Base64 塞进 Socket 管道这会导致消息拥塞甚至让所有人的聊天卡顿。标准流程上传前端 Axios 接口将文件传到服务器如 OSS、MinIO。获取 URL服务器返回文件的访问地址例如http://cdn.com/a.xlsx。发消息通过 Socket.io 发送一个包含 URL 和文件类型的 JSON 对象。// 发送文件的消息结构 const fileMsg { type: file, // 或者 image content: http://xxx.com/test.xlsx, fileName: 2026年报表.xlsx, fileSize: 1.2MB }; socket.emit(chat_message, fileMsg);二、 鉴权Auth Query为了安全不能让谁都能连上你的 Socket。通常在建立连接的那一刻就要验证身份。JavaScriptimport { io } from socket.io-client; const socket io(http://localhost:3000, { // 方式 1auth 属性推荐更安全数据在握手包里 auth: { token: uni.getStorageSync(token) }, // 方式 2query 属性放在 URL 参数里容易被拦截或在日志里暴露 query: { room: room_101 } });后端Node.js 示例拦截io.use((socket, next) { const token socket.handshake.auth.token; if (validateToken(token)) { next(); // 校验通过 } else { next(new Error(鉴权失败)); } });JavaScript四、 消息去重与有序性这是高并发下的难点。1. 消息去重防止重复发送前端生成nonce(唯一 ID)每次点击发送按钮生成一个 UUID。后端校验后端维护一个最近消息 ID 集合如果发现 ID 重复直接丢弃不进行广播。2. 有序性防止消息乱序由于网络抖动消息 A 先发可能后到。解决每一条消息都带上一个服务端生成的递增sequence_id或高精度时间戳。前端拿到消息后先按这个 ID 放入缓冲区排序然后再渲染到屏幕上。直接看代码吧// useChat.ts import { ref } from vue; import { io } from socket.io-client; export const useChat (roomId) { const socket io(wss://api.thinglinks.com, { auth: { token: YOUR_TOKEN } }); const chatList ref([]); // 1. 处理接收去重与排序 socket.on(message, (newMsg) { // 检查 ID 是否已存在去重 if (chatList.value.find(m m.id newMsg.id)) return; chatList.value.push(newMsg); // 按照时间戳排序有序 chatList.value.sort((a, b) a.time - b.time); }); // 2. 发送逻辑区分类型 const send (type, content) { const msg { id: generateUUID(), // 前端先给个临时 ID type: type, // text, image, file content: content, time: Date.now() }; socket.emit(message, msg); }; return { chatList, send }; };