WebSocket 详解:构建一个复杂的实时聊天应用
文章目录
- 一、前言
- 二、WebSocket 基础
- 2.1 WebSocket 与 HTTP 的区别
- 2.2 WebSocket 的优点
- 三、搭建 WebSocket 服务端
- 3.1 安装 `ws` 和 `redis` 库
- 3.2 创建 WebSocket 服务端
- 3.3 创建用户身份验证
- 四、前端实现 WebSocket 客户端
- 4.1 创建 Vue 3 项目
- 4.2 实现 WebSocket 连接和用户注册
- 五、WebSocket 安全性与优化
- 5.1 消息加密
- 5.2 连接池与负载均衡
一、前言
在实时应用的开发中,WebSocket 已经成为实现高效、低延迟实时通讯的关键技术。通过建立持久的双向连接,WebSocket 不仅可以减少网络请求的开销,还能支持高效的数据传输。在本教程中,我们将创建一个更复杂的聊天应用,除了实现基本的 WebSocket 连接外,还将扩展一些常见的应用场景:私聊、群聊、消息持久化、用户身份验证等。
二、WebSocket 基础
2.1 WebSocket 与 HTTP 的区别
- HTTP 协议:每次客户端请求时,都会重新建立连接,适用于请求-响应模式。
- WebSocket 协议:创建一个持久连接,支持全双工通信,使得数据传输更高效。客户端和服务器之间能够实时发送和接收数据。
2.2 WebSocket 的优点
- 低延迟:通过持久连接,避免了频繁的请求和响应开销。
- 双向通信:客户端和服务器可以实时交换数据。
- 减少带宽消耗:长期保持一个连接,不再需要重新建立连接。
三、搭建 WebSocket 服务端
我们将使用 Node.js 和 ws 库创建 WebSocket 服务器,并通过 Redis 实现群聊的消息广播。
3.1 安装 ws 和 redis 库
首先,创建 Node.js 项目并安装所需的依赖:
npm init -y
npm install ws redis
3.2 创建 WebSocket 服务端
在 server.js 中,我们将实现一个 WebSocket 服务器,支持群聊和私聊功能。
// server.js
const WebSocket = require('ws');
const redis = require('redis');// 创建 WebSocket 服务器,监听端口 8080
const wss = new WebSocket.Server({ port: 8080 });// 连接 Redis 客户端
const client = redis.createClient();// 存储所有连接的 WebSocket 客户端
let users = {};wss.on('connection', ws => {console.log('客户端已连接');// 处理消息接收ws.on('message', (message) => {const data = JSON.parse(message);const { type, user, content, target } = data;if (type === 'chat') {// 广播消息到所有客户端(群聊)broadcast(user, content);} else if (type === 'private') {// 私聊消息(发送到指定目标)privateMessage(user, target, content);} else if (type === 'history') {// 请求聊天记录getHistory(ws);}});// 连接成功时,给客户端一个欢迎消息ws.on('open', () => {ws.send(JSON.stringify({ user: 'server', content: '欢迎来到聊天室!' }));});// 监听客户端断开连接ws.on('close', () => {console.log('客户端已断开连接');// 用户断开连接后,清理用户信息Object.keys(users).forEach((key) => {if (users[key] === ws) {delete users[key];}});});// 广播消息到所有客户端function broadcast(user, content) {wss.clients.forEach(client => {if (client.readyState === WebSocket.OPEN) {client.send(JSON.stringify({ user, content }));}});// 将聊天记录保存到 Redis 中client.rpush('chatHistory', JSON.stringify({ user, content }));}// 私聊功能:发送消息给特定的用户function privateMessage(user, target, content) {const targetSocket = users[target];if (targetSocket) {targetSocket.send(JSON.stringify({ user, content }));} else {ws.send(JSON.stringify({ user: 'server', content: '用户不在线' }));}}// 获取历史聊天记录function getHistory(ws) {client.lrange('chatHistory', 0, -1, (err, messages) => {if (err) {ws.send(JSON.stringify({ user: 'server', content: '获取聊天记录失败' }));} else {ws.send(JSON.stringify({ user: 'server', content: messages }));}});}// 注册用户ws.on('message', (data) => {const message = JSON.parse(data);if (message.type === 'register') {users[message.user] = ws;console.log(`${message.user} 已注册`);}});
});
3.3 创建用户身份验证
为了实现用户身份验证,我们可以通过 WebSocket 连接时传递一个 token,来验证用户的身份。
// 用户身份验证
ws.on('connection', (socket, request) => {const token = request.url.split('token=')[1]; // 从 URL 中获取 tokenif (isValidToken(token)) {// 如果 token 验证通过,继续连接socket.send('身份验证通过');} else {socket.close(); // 否则关闭连接}
});
四、前端实现 WebSocket 客户端
我们将使用 Vue 3 创建聊天应用,并实现消息发送、接收、私聊等功能。
4.1 创建 Vue 3 项目
通过 Vue CLI 创建一个新的 Vue 项目:
vue create websocket-chat
4.2 实现 WebSocket 连接和用户注册
在 ChatRoom.vue 中实现 WebSocket 客户端:
<template><div class="chat-room"><div class="messages"><div v-for="(message, index) in messages" :key="index" class="message"><strong>{{ message.user }}:</strong> {{ message.content }}</div></div><input v-model="newMessage" @keyup.enter="sendMessage" placeholder="Type a message..." /><button @click="sendPrivateMessage">私聊</button></div>
</template><script>
export default {data() {return {socket: null,messages: [],newMessage: '',user: 'User' + Math.floor(Math.random() * 1000),targetUser: '', // 私聊目标用户};},mounted() {this.socket = new WebSocket('ws://localhost:8080');this.socket.onopen = () => {this.socket.send(JSON.stringify({ type: 'register', user: this.user }));};this.socket.onmessage = (event) => {const message = JSON.parse(event.data);this.messages.push(message);this.scrollToBottom();};},methods: {sendMessage() {if (this.newMessage.trim()) {this.socket.send(JSON.stringify({ type: 'chat', user: this.user, content: this.newMessage }));this.newMessage = '';}},sendPrivateMessage() {if (this.targetUser && this.newMessage.trim()) {this.socket.send(JSON.stringify({type: 'private',user: this.user,target: this.targetUser,content: this.newMessage,}));this.newMessage = '';}},scrollToBottom() {const container = this.$refs.messageContainer;container.scrollTop = container.scrollHeight;},},
};
</script>
五、WebSocket 安全性与优化
5.1 消息加密
为了保障通信安全,可以使用 AES 加密协议加密传输的消息内容,确保数据在传输过程中不会被窃取。
5.2 连接池与负载均衡
当 WebSocket 服务器需要处理大量连接时,可以使用连接池和负载均衡技术。例如,使用 Nginx 配置 WebSocket 反向代理。
到这里,这篇文章就和大家说再见啦!我的主页里还藏着很多 篇 前端 实战干货,感兴趣的话可以点击头像看看,说不定能找到你需要的解决方案~
创作这篇内容花了很多的功夫。如果它帮你解决了问题,或者带来了启发,欢迎:
点个赞❤️ 让更多人看到优质内容
关注「前端极客探险家」🚀 每周解锁新技巧
收藏文章⭐️ 方便随时查阅
📢 特别提醒:
转载请注明原文链接,商业合作请私信联系
感谢你的阅读!我们下篇文章再见~ 💕

相关文章:
WebSocket 详解:构建一个复杂的实时聊天应用
文章目录 一、前言二、WebSocket 基础2.1 WebSocket 与 HTTP 的区别2.2 WebSocket 的优点 三、搭建 WebSocket 服务端3.1 安装 ws 和 redis 库3.2 创建 WebSocket 服务端3.3 创建用户身份验证 四、前端实现 WebSocket 客户端4.1 创建 Vue 3 项目4.2 实现 WebSocket 连接和用户注…...
详解七大排序
目录 一.直接插入排序 (1)基本思想 (2)算法步骤 (3)代码实现 (4)算法特性 (5)算法优化 (6)示例演示 二.希尔排序 (…...
python爬虫:小程序逆向实战教程
根据我之前发表的文章,我们进行延伸实战https://blog.csdn.net/weixin_64809364/article/details/146981598?spm1001.2014.3001.5501 1. 想要爬取什么小程序,我们进行搜索 2. 找到我们vx小程序的文件地址,我们就可以进行破解 破解步骤强看…...
day 8 TIM定时器
一、STM32 定时器概述 1. 定时器的概述定时器的基本功能,但是 STM32 的定时器除了具有定时功能之外,也具有定时器中断功能,还具有输入捕获(检测外部信号)以及输出比较功能(输出不同的脉冲)&…...
全星 研发项目管理APQP 软件:驱动汽车及制造业研发升级的数字化引擎
全星 APQP 软件:驱动汽车及制造业研发升级的数字化引擎 在汽车及制造业竞争白热化的当下,如何高效推进研发项目,同时确保严格合规,成为企业亟待解决的难题。 全星研发项目管理 APQP 软件系统,凭借卓越的功能与显著优势…...
【VUE】RuoYi-Vue3项目结构的分析
【VUE】RuoYi-Vue3项目结构的分析 1. 项目地址2. RuoYi-Vue3项目结构2.1 整体结构2.2 package.json2.2.1 🧾 基本信息2.2.2 🔧 脚本命令(scripts)2.2.3 🌍 仓库信息2.2.4 📦 项目依赖(dependenc…...
智能体和RPA都需要程序思维,如何使用影刀的变量?
欢迎来到涛涛聊AI, 不管AI还是RPA,都需要用到编程思想才能完成批量工作。今天研究了下影刀的变量。 变量类型 根据变量值选择相应的类型,可选择任意一种影刀所支持的数据类型 变量值 指定变量中保存的值,会根据不同的类型设置…...
详解 MySQL 三层 B+ 树能存多少数据的计算方法
MySQL三层B树能存多少数据 1. 内部节点(非叶子节点)的容量计算2. 叶子节点的数据记录容量3. 三层 B 树的存储能力计算4. 总结 1. 内部节点(非叶子节点)的容量计算 设定参数如下: P:每个节点页的大小&…...
论文笔记(七十五)Auto-Encoding Variational Bayes
Auto-Encoding Variational Bayes 文章概括摘要1 引言2 方法2.1 问题场景2.2 变分下界2.3 SGVB估计器与AEVB算法2.4 重参数化技巧 3 示例:变分自编码器(Variational Auto-Encoder)4 相关工作5 实验6 结论7 未来工作 文章概括 引用࿱…...
Sentinel[超详细讲解]-7 -之 -熔断降级[异常比例阈值]
📖 主要讲解熔断降级之 --- 异常比例阈值 🚀 1️⃣ 背景 Sentinel 以流量作为切入点,提供了很多的丰富的功能,例如🤗: 流量控制,熔断降级等,它能够有效的适用各个复杂的业务场景&am…...
《基于 C++ 的怪物掉落武器功能开发》
一、项目背景 在游戏开发中,怪物掉落武器机制是丰富游戏玩法与提升玩家体验的关键部分。本功能基于 C 语言开发,旨在实现一套逻辑清晰、扩展性强的怪物掉落武器系统,为游戏核心玩法增添策略性与趣味性。 二、功能需求 (一&#…...
C++11观察者模式示例
该示例代码采用C11标准,解决以下问题: 消除了类继承的强耦合方式;通知接口使用可变参数模板,支持任意参数; 示例代码 .h文件如下: #include <functional> #include <string> #include <…...
算法设计学习10
实验目的及要求: 本查找实验旨在使学生深入了解不同查找算法的原理、性能特征和适用场景,培养其在实际问题中选择和应用查找算法的能力。通过实验,学生将具体实现多种查找算法,并通过性能测试验证其在不同数据集上的表现ÿ…...
configurable_alternatives 方法与使用技巧
核心功能与应用场景 在开发调试过程中,当需要动态替换链中的完整组件(如大语言模型、提示词模板等)并保持对话连续性时,可通过 configurable_alternatives() 实现运行时组件热替换。典型场景包括: 调试时切换不同版…...
Angular 2 模板语法详解
Angular 2 模板语法详解 引言 Angular 2 作为一款强大的前端框架,以其组件化的开发模式和高效的性能被众多开发者所青睐。模板语法是Angular 2中用于定义组件UI的关键部分。本文将详细介绍Angular 2的模板语法,帮助开发者更好地理解和运用这一功能。 模板语法概述 Angula…...
对称加密:原理、算法与应用全解析
对称加密作为密码学领域的核心技术,凭借其高效性与广泛应用,在数据安全领域占据重要地位。本文将从基础概念、历史发展、核心算法到实际应用场景,全方位解析对称加密技术的全貌,并探讨其面临的挑战与未来方向。 一、对称加密的核心…...
多线程编程中的锁策略
目录 1.悲观锁vs乐观锁 关键总结 悲观锁: 乐观锁: 选择建议 用 悲观锁 当: 用 乐观锁 当: 2.重量级锁vs轻量级锁 选择建议 用 轻量级锁: 用 重量级锁: 3.挂起等待锁vs自旋锁 关键细节说明 选择…...
win10 笔记本电脑安装 pytorch+cuda+gpu 大模型开发环境过程记录
win10 笔记本电脑安装 pytorchcudagpu 大模型开发环境过程记录 文章部分内容参考 deepseek。 以下使用命令行工具 mingw64。 安装 Anaconda 安装位置: /c/DEVPACK/Anaconda3 然后安装 Python 3.10.16 (略) $ conda create -n pytorch_…...
Layout Inspector平替跨平台布局分析器のAppium Inspector
引言 因为我有一个api为26的设备,因为 Layout Inspector 无法在 API 26 以下设备上使用,并且现在AS的 Hierarchy Viewer 和Android Device Monitor 均已经在SDK中剔除,故想再搜一个pc版的布局查看器,发现Appium Inspector学习成本…...
基于sklearn实现文本摘要思考
和各位小伙伴分享一下使用sklearn进行文本摘要的思考。 第一版本 原理 提取式文本摘要的基本原理是: 将文本分割成句子 计算每个句子的重要性(权重) 选择权重最高的几个句子组成摘要 常用的句子权重计算方法: TF-IDF:基于词频-逆文档频…...
常见NLP指标PPL,F1,Rouge-L,Accuracy (CLS),Accuracy (EM)总结
常见NLP指标PPL,F1,Rouge-L总结 1.PPL 2.F1 3.Rouge-L 4.Accuracy (CLS) 5.Accuracy (EM)...
Redis数据结构之ZSet
目录 1.概述2.常见操作2.1 ZADD2.2 ZRANGE2.3 ZREVRANGE2.4 ZRANGEBYSCORE2.5 ZSCORE2.6 ZCARD2.6 ZREM2.7 ZINCRBY2.8 ZCOUNT2.9 ZMPOP2.10 ZRANK2.11 ZREVRANK 3.总结 1.概述 ZSet和Set一样也是String类型元素的集合,且不允许重复的成员,不同的是ZSet…...
使用binance-connector库获取Binance全市场的币种价格,然后选择一个币种进行下单
一个完整的示例,展示如何使用 api 获取Binance全市场的币种价格,然后选择一个最便宜的币种进行下单操作 代码经过修改,亲测可用,目前只可用于现货,合约的待开发 获取市场价格:使用client.ticker_price()获取所有交易对的当前价格 账户检查:获取账户余额,确保有足够的资…...
磁盘分析工具合集:告别C盘焦虑!
今天李师傅带大家盘点五款硬盘空间分析利器,帮你精准定位那些"吃空间"的元凶,让C盘告别臃肿烦恼! 一、WizTree 这款NTFS磁盘的"透视眼"堪称效率典范。它通过直接读取硬盘主文件表(MFT)实现秒级扫描,1TB机械…...
20250405在荣品的PRO-RK3566开发板使用Rockchip原厂的buildroot系统来适配gmac1
【暂时还没有解决让PRO-RK3566的eth0/gmac1开机就启动】 PRO-RK3566作为iperf服务器: rootrk3566-buildroot:/# ifconfig rootrk3566-buildroot:/# ifconfig -a rootrk3566-buildroot:/# ifconfig eth0 up rootrk3566-buildroot:/# ifconfig rootrk3566-buildroot:/…...
Spring / Spring Boot 的@MapperScan 和 @Repository
MapperScan 和 Repository 是两个与数据访问层相关的注解,它们在功能上有一定的联系,但也有明显的区别。 一、相同点 1. 都与数据访问层相关 MapperScan:用于扫描 MyBatis 的 Mapper 接口。MyBatis 是一个流行的持久层框架,Mapp…...
SDL中SDL_AudioSpec结构体参数
文章目录 ✅ SDL_AudioSpec 结构体定义📌 每个字段详细解释 设置依据1. freq:采样频率(Sample Rate)2. format:采样格式(Sample Format)3. channels:通道数(Channels&am…...
每日一题(小白)模拟娱乐篇14
直接理解题意,一分钟扩散一次,那么2020分钟也就是需要循环2020次,然后加入扩散后的条件,每一个次扩散使方格子的总量1(只要有一个点扩散就无需看其他的点),若干次循环过后总数之和即所有黑色格子…...
使用 Python 爬取并打印双色球近期 5 场开奖数据
使用 Python 爬取并打印双色球近期 5 场开奖数据 前期准备安装所需库 完整代码代码解析 1. 导入必要的库2. 定义函数 get_recent_five_ssq 3. 设置请求的 URL 和 Headers 4. 发送请求并处理响应5. 解析 HTML 内容6. 提取并打印数据7. 错误处理 首先看下运行的效果图:…...
再见VS Code!Google IDE 正颠覆传统开发体验
云端开发的革命:Google Project IDX 如何颠覆传统开发体验 在软件开发领域,Google 最新推出的 Project IDX 绝非仅仅是另一个“基于浏览器的 VS Code”——它是一次真正的范式转变。与 VS Code、Cursor 等传统工具不同,IDX 是一个完全云原生的…...
