WebSocket 详解:构建一个复杂的实时聊天应用

news2025/4/6 10:37:41

文章目录

  • 一、前言
  • 二、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.jsws 库创建 WebSocket 服务器,并通过 Redis 实现群聊的消息广播。

3.1 安装 wsredis

首先,创建 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 中获取 token
  if (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 反向代理。


到这里,这篇文章就和大家说再见啦!我的主页里还藏着很多 篇 前端 实战干货,感兴趣的话可以点击头像看看,说不定能找到你需要的解决方案~
创作这篇内容花了很多的功夫。如果它帮你解决了问题,或者带来了启发,欢迎:
点个赞❤️ 让更多人看到优质内容
关注「前端极客探险家」🚀 每周解锁新技巧
收藏文章⭐️ 方便随时查阅
📢 特别提醒:
转载请注明原文链接,商业合作请私信联系
感谢你的阅读!我们下篇文章再见~ 💕

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2329158.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python爬虫:小程序逆向实战教程

根据我之前发表的文章&#xff0c;我们进行延伸实战https://blog.csdn.net/weixin_64809364/article/details/146981598?spm1001.2014.3001.5501 1. 想要爬取什么小程序&#xff0c;我们进行搜索 2. 找到我们vx小程序的文件地址&#xff0c;我们就可以进行破解 破解步骤强看…

day 8 TIM定时器

一、STM32 定时器概述 1. 定时器的概述定时器的基本功能&#xff0c;但是 STM32 的定时器除了具有定时功能之外&#xff0c;也具有定时器中断功能&#xff0c;还具有输入捕获&#xff08;检测外部信号&#xff09;以及输出比较功能&#xff08;输出不同的脉冲&#xff09;&…

全星 研发项目管理APQP 软件:驱动汽车及制造业研发升级的数字化引擎

全星 APQP 软件&#xff1a;驱动汽车及制造业研发升级的数字化引擎 在汽车及制造业竞争白热化的当下&#xff0c;如何高效推进研发项目&#xff0c;同时确保严格合规&#xff0c;成为企业亟待解决的难题。 全星研发项目管理 APQP 软件系统&#xff0c;凭借卓越的功能与显著优势…

【VUE】RuoYi-Vue3项目结构的分析

【VUE】RuoYi-Vue3项目结构的分析 1. 项目地址2. RuoYi-Vue3项目结构2.1 整体结构2.2 package.json2.2.1 &#x1f9fe; 基本信息2.2.2 &#x1f527; 脚本命令&#xff08;scripts&#xff09;2.2.3 &#x1f30d; 仓库信息2.2.4 &#x1f4e6; 项目依赖&#xff08;dependenc…

智能体和RPA都需要程序思维,如何使用影刀的变量?

欢迎来到涛涛聊AI&#xff0c; 不管AI还是RPA&#xff0c;都需要用到编程思想才能完成批量工作。今天研究了下影刀的变量。 变量类型 根据变量值选择相应的类型&#xff0c;可选择任意一种影刀所支持的数据类型 变量值 指定变量中保存的值&#xff0c;会根据不同的类型设置…

论文笔记(七十五)Auto-Encoding Variational Bayes

Auto-Encoding Variational Bayes 文章概括摘要1 引言2 方法2.1 问题场景2.2 变分下界2.3 SGVB估计器与AEVB算法2.4 重参数化技巧 3 示例&#xff1a;变分自编码器&#xff08;Variational Auto-Encoder&#xff09;4 相关工作5 实验6 结论7 未来工作 文章概括 引用&#xff1…

Sentinel[超详细讲解]-7 -之 -熔断降级[异常比例阈值]

&#x1f4d6; 主要讲解熔断降级之 --- 异常比例阈值 &#x1f680; 1️⃣ 背景 Sentinel 以流量作为切入点&#xff0c;提供了很多的丰富的功能&#xff0c;例如&#x1f917;&#xff1a; 流量控制&#xff0c;熔断降级等&#xff0c;它能够有效的适用各个复杂的业务场景&am…

C++11观察者模式示例

该示例代码采用C11标准&#xff0c;解决以下问题&#xff1a; 消除了类继承的强耦合方式&#xff1b;通知接口使用可变参数模板&#xff0c;支持任意参数&#xff1b; 示例代码 .h文件如下&#xff1a; #include <functional> #include <string> #include <…

win10 笔记本电脑安装 pytorch+cuda+gpu 大模型开发环境过程记录

win10 笔记本电脑安装 pytorchcudagpu 大模型开发环境过程记录 文章部分内容参考 deepseek。 以下使用命令行工具 mingw64。 安装 Anaconda 安装位置&#xff1a; /c/DEVPACK/Anaconda3 然后安装 Python 3.10.16 &#xff08;略&#xff09; $ conda create -n pytorch_…

Layout Inspector平替跨平台布局分析器のAppium Inspector

引言 因为我有一个api为26的设备&#xff0c;因为 Layout Inspector 无法在 API 26 以下设备上使用&#xff0c;并且现在AS的 Hierarchy Viewer 和Android Device Monitor 均已经在SDK中剔除&#xff0c;故想再搜一个pc版的布局查看器&#xff0c;发现Appium Inspector学习成本…

常见NLP指标PPL,F1,Rouge-L,Accuracy (CLS),Accuracy (EM)总结

常见NLP指标PPL&#xff0c;F1&#xff0c;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类型元素的集合&#xff0c;且不允许重复的成员&#xff0c;不同的是ZSet…

磁盘分析工具合集:告别C盘焦虑!

今天李师傅带大家盘点五款硬盘空间分析利器&#xff0c;帮你精准定位那些"吃空间"的元凶&#xff0c;让C盘告别臃肿烦恼&#xff01; 一、WizTree 这款NTFS磁盘的"透视眼"堪称效率典范。它通过直接读取硬盘主文件表(MFT)实现秒级扫描&#xff0c;1TB机械…

20250405在荣品的PRO-RK3566开发板使用Rockchip原厂的buildroot系统来适配gmac1

【暂时还没有解决让PRO-RK3566的eth0/gmac1开机就启动】 PRO-RK3566作为iperf服务器&#xff1a; rootrk3566-buildroot:/# ifconfig rootrk3566-buildroot:/# ifconfig -a rootrk3566-buildroot:/# ifconfig eth0 up rootrk3566-buildroot:/# ifconfig rootrk3566-buildroot:/…

每日一题(小白)模拟娱乐篇14

直接理解题意&#xff0c;一分钟扩散一次&#xff0c;那么2020分钟也就是需要循环2020次&#xff0c;然后加入扩散后的条件&#xff0c;每一个次扩散使方格子的总量1&#xff08;只要有一个点扩散就无需看其他的点&#xff09;&#xff0c;若干次循环过后总数之和即所有黑色格子…

使用 Python 爬取并打印双色球近期 5 场开奖数据

使用 Python 爬取并打印双色球近期 5 场开奖数据 前期准备安装所需库 完整代码代码解析 1. 导入必要的库2. 定义函数 get_recent_five_ssq 3. 设置请求的 URL 和 Headers 4. 发送请求并处理响应5. 解析 HTML 内容6. 提取并打印数据7. 错误处理 首先看下运行的效果图&#xff1a…

再见VS Code!Google IDE 正颠覆传统开发体验

云端开发的革命&#xff1a;Google Project IDX 如何颠覆传统开发体验 在软件开发领域&#xff0c;Google 最新推出的 Project IDX 绝非仅仅是另一个“基于浏览器的 VS Code”——它是一次真正的范式转变。与 VS Code、Cursor 等传统工具不同&#xff0c;IDX 是一个完全云原生的…

AI+自动化测试:如何让测试编写效率提升10倍?

文章目录 摘要传统自动化测试的痛点编写测试用例太费时间测试覆盖率难以保证UI 测试维护成本高 AI 如何优化自动化测试&#xff1f;AI 生成单元测试&#xff1a;减少重复工作&#xff0c;提高覆盖率传统方法 VS AI 方法 使用 AI 生成 Python 单元测试自动补全边界情况传统方法 …

01-STM32(介绍、工具准备、新建工程)p1-4

文章目录 工具准备和介绍硬件设备stm32简介和arm简介stm32简介STM32命名规则STM32选型STM32F103C8T6最小系统板引脚定义STM32启动配置STM32最小系统电路ARM简介 软件安装注册器件支持包安装ST-LINK驱动安装USB转串口驱动 新建工程创建stm32工程STM32工程编译和下载型号分类及缩…

Win10定时任务计划无法显示要执行的EXE任务程序界面,问题解决办法

用C#开发的一款WINFORM程序&#xff0c;在电脑测试一切顺利&#xff0c;运行结果正确。但用电脑的定时任务执行时&#xff0c;程序界面不显示&#xff0c;重启电脑、各种试都不行&#xff0c;最终问题解决。 解决办法&#xff1a; 要选“只在用户登陆时运行”&#xff0c;才能执…