当前位置: 首页 > news >正文

IM(即时通讯)系统

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. 安装依赖

    Bash
    npm install socket.io-client

    2. 封装useSocket.ts

    TypeScript
    import { 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. 页面使用

    HTML
    <template> <div class="chat-container"> <p v-if="!isConnected">正在连接服务器...</p> <div v-for="(item, index) in messages" :key="index"> {{ item.text }} </div> <input v-model="inputMsg" @keyup.enter="handleSend" /> <button @click="handleSend">发送</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 秒)发个“乒乓包”,确认对方还活着,否则连接会被运营商强行掐断。

  • 消息去重与有序性:在高并发下,消息可能会乱序,前端需要根据msgIdtimestamp进行排序。

  • 安全性: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。通常在建立连接的那一刻就要验证身份。

JavaScript

import { io } from 'socket.io-client'; const socket = io('http://localhost:3000', { // 方式 1:auth 属性(推荐,更安全,数据在握手包里) auth: { token: uni.getStorageSync('token') }, // 方式 2:query 属性(放在 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 }; };
http://www.cnnetsun.cn/news/1922501.html

相关文章:

  • JPEXS Free Flash Decompiler深度解析:从字节码到可读代码的技术揭秘
  • 3步解锁小爱音箱全能音乐中心:告别版权限制的自由听歌方案
  • 终极指南:如何用RyzenAdj释放AMD锐龙处理器全部潜能
  • SQLmap-GUI终极指南:如何快速掌握图形化SQL注入渗透测试工具
  • 嵌入式:中断风暴成因与应对
  • NaViL-9B开源镜像优势解析:Clash清理+多卡兼容+eager注意力回退
  • 痛点驱动:图片插入Word文档工具在3个典型场景的应用
  • 基于 CNN-SE Attention-ITCN 多模态融合的多输入单输出回归预测模型【MATLAB】
  • MyBatis-Plus 分页查询两种实现方案
  • 手把手教你用STM32CubeMX配置PWM,轻松玩转L298N和L9110S电机调速
  • 如何3步掌握FunClip:开源AI视频智能剪辑工具终极指南
  • 如何利用开源工具实现网盘下载速度突破:高效解决方案指南
  • Visual C++运行库终极指南:一键解决DLL缺失问题的完整方案
  • APM飞控实战:从零搭建一台稳定四旋翼
  • 用STAR数据集搞定卫星图像分析:从对象检测到场景关系推理的完整实战指南
  • 在LVGL上实现一个可交互的音频均衡器:手把手教你用贝塞尔曲线绘制平滑EQ曲线
  • 数字化车间无线联网解决方案
  • 告别电脑噪音烦恼:5分钟掌握Windows风扇智能控制神器FanControl
  • 终极指南:如何用MAA实现明日方舟全自动日常管理
  • Windows风扇控制神器:用FanControl打造你的专属静音散热系统
  • 如何在Mac与Windows间架起高效通信桥梁:飞秋Mac版完全指南
  • 3步搞定全网资源下载:告别繁琐操作,用res-downloader轻松获取无水印内容
  • 网络工程师避坑指南:H3C HCL_v3.0.1.1+WSL2共存配置全流程
  • 告别手动!用C# .NET给AutoCAD写个批量打印PDF的脚本(附完整代码)
  • 终极桌面革命:用Rainmeter打造你的Windows数字画布
  • 告别天价API!手把手教你用阿里开源Wan2.1-T2V-1.3B模型,打造个人免费文生视频工具
  • 给Xilinx K7 FPGA做远程固件升级,我是如何用Multiboot实现‘双保险’的?
  • 手把手教你使用env()和constant()解决微信小程序底部安全区域问题
  • SenseVoice-Small ONNX部署教程:ARM架构设备(树莓派/国产芯片)适配实录
  • 软件估算中的敏捷估算方法实践指南