基于websocket与node搭建简易聊天室
一、前言
上一篇文章介绍了websocket的详细用法与工具类的封装,本篇就基于websocket搭建一个简易实时的聊天室。
在本篇开始之前也可以去回顾一下websocket详细用法:WebSocket详解与封装工具类

二、基于node搭建后台websocket服务
首先确认本机电脑中是否安装node,可以通过cmd打开命令窗口运行node -v查看node版本;
- 建议创建一个空项目:
npm init
- 一路回车就行,然后就得到了一个package.json的配置文件;安装
ws模块
npm i ws
- 新建app.js文件,源码如下:
const WebSocket = require('ws');
// 随机姓名
const names = ['赵', '钱', '孙', '李', '周', '吴', '郑', '王', '冯', '陈', '褚', '卫', '蒋', '沈', '韩', '杨', '朱', '秦', '尤', '许', '何','吕', '施', '张', '孔', '曹', '严', '华', '金', '魏', '陶', '姜', '戚', '谢', '邹', '喻', '柏', '水', '窦', '章', '云', '苏', '潘', '葛','奚', '范', '彭', '郎', '鲁', '韦', '昌', '马', '苗', '凤', '花', '方', '俞', '任', '袁', '柳', '酆', '鲍', '史', '唐', '费', '廉', '岑','薛', '雷', '贺', '倪', '汤', '滕', '殷', '罗', '毕', '郝', '邬', '安', '常', '乐', '于', '时', '傅', '皮', '卞', '齐', '康', '伍', '余','元', '卜', '顾', '孟', '平', '黄', '和', '穆', '萧', '尹'
];
// 获取随便昵称
const getRandom = (min, max) => {return Math.floor(Math.random() * (min - max) + max)
};
// 创建 WebSocket 服务器实例
const wss = new WebSocket.Server({port: 8080
});
// 监听连接事件
wss.on('connection', function(socket) {console.log('新连接');const randomIndex = getRandom(0, names.length - 1);socket.nickname = names.splice(randomIndex, 1)[0];sendMessageToClient( '连接成功!进入聊天室!');// 监听接收消息事件socket.on('message', function(message) {sendMessageToClient(message);});// 监听接收消息事件socket.on('close', function() {// 广播消息给所有客户端wss.clients.forEach(function each(client) {if (client.readyState === WebSocket.OPEN) {client.send(JSON.stringify({nickname: socket.nickname,msg: '退出聊天室!',}));}});});// 监听接收消息事件socket.on('error', function() {// 广播消息给所有客户端wss.clients.forEach(function each(client) {if (client.readyState === WebSocket.OPEN) {client.send(JSON.stringify({nickname: socket.nickname,msg: '网络不佳,连接失败 !',}));}});});// 发送消息到客户端function sendMessageToClient(message) {let targetMsg = message instanceof Buffer ? message.toString() : message;// 广播消息给所有客户端wss.clients.forEach(function each(client) {if (client.readyState === WebSocket.OPEN) {client.send(JSON.stringify({nickname: socket.nickname,msg: targetMsg,}));}});}
});
- 最后启动node服务:
node app.js;
三、前端构建聊天室
3.1 确定功能点
- 会话框中展示聊天内容;
- 输入框与发送按钮发送消息内容;
- 连接websocket,监听实时消息展示到界面中;
3.2 界面结构搭建

代码结构:
<div class="main_container"><!-- 消息框 --><div id="msgList"></div><!-- 发送消息 --><div class="controls"><input type="text" class="pushMsg" /><button id="btn">发送</button></div>
</div>
3.3 代码逻辑
-
引入之前封装的websocket工具类;
<script src="./utils/websocket.js"></script> -
实例化连接websocket;
const newWebSocket = new WebSocketClient('ws:localhost:8080'); newWebSocket.connect(); -
定义消息列表,监听返回消息信息,根据消息展示到界面中;
// 消息列表 const msgList = []; newWebSocket.addEventListener('message', handleMessage); // 处理返回数据 function handleMessage(msg) {const msgData = JSON.parse(msg.data || '{}');console.log(msgData, "返回数据====");if (msgData && typeof msgData.msg === 'string' && !msgData.msg.includes('ping')) {msgList.push({name: msgData.nickname,msg: msgData.msg,});const str = msgList.reduce((cur, next) => {let curMsg = '';if (next.msg.includes('连接')) {curMsg = `<div class="center_msg">玩家:${next.name}_${next.msg}</div>`;} else {curMsg = `<div class="msg_line"><div class="avatar">${next.name}</div><div class="msg_text">${next.msg}</div></div>`;}return cur += curMsg;}, '');$('#msgList').html(str);// 获取设置了滚动属性的div标签const div = document.getElementById('msgList');// 设置滚动的顶点坐标为滚动的总高度div.scrollTop = div.scrollHeight;} }newWebSocket.addEventListener('message', handleMessage); // 处理返回数据 function handleMessage(msg) {const msgData = JSON.parse(msg.data || '{}');console.log(msgData, "返回数据====");if (msgData && typeof msgData.msg === 'string' && !msgData.msg.includes('ping')) {msgList.push({name: msgData.nickname,msg: msgData.msg,});const str = msgList.reduce((cur, next) => {let curMsg = '';if (next.msg.includes('连接')) {curMsg = `<div class="center_msg">玩家:${next.name}_${next.msg}</div>`;} else {curMsg = `<div class="msg_line"><div class="avatar">${next.name}</div><div class="msg_text">${next.msg}</div></div>`;}return cur += curMsg;}, '');$('#msgList').html(str);// 获取设置了滚动属性的div标签const div = document.getElementById('msgList');// 设置滚动的顶点坐标为滚动的总高度div.scrollTop = div.scrollHeight;} } -
监听输入框回车事件,与发送按钮点击事件,发送消息;
// 监听发送按钮 $('#btn').on('click', sendMessage);// 输入框回车事件 $('.pushMsg').keydown(function(event) {if (event.key === 'Enter') {sendMessage();} }); // 发送消息 function sendMessage() {const msg = $('.pushMsg').val();if (msg) {newWebSocket.send(`${msg}`);$('.pushMsg').val('');} }
四、涉及小知识点
-
取消滚动条的展示,发送消息后默认展示最下方数据;
#msgList::-webkit-scrollbar {width: 0; }// 获取设置了滚动属性的div标签 const div = document.getElementById('msgList'); // 设置滚动的顶点坐标为滚动的总高度 div.scrollTop = div.scrollHeight; -
输入框监听keydown事件,当key为
Enter时发送消息(也可设置其他按键)// 输入框回车事件 $('.pushMsg').keydown(function(event) {if (event.key === 'Enter') {sendMessage();} }); -
取消input的光标进入的表框效果
outline: none; -
鼠标小手的出现
cursor: pointer;
五、聊天室完整前端源码
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>聊天通信</title><script src="./utils/jquery.min.js"></script><script src="./utils/websocket.js"></script><style>.main_container {width: 500px;margin: auto;}#msgList {width: 500px;height: 400px;overflow: auto;border: 2px solid #8491fe;border-radius: 10px;padding: 6px;background-color: #ebffff;box-sizing: border-box;}#msgList::-webkit-scrollbar {width: 0;}.msg_line {margin: 10px 0;display: flex;flex-wrap: wrap;}.avatar {width: 30px;height: 30px;border-radius: 50%;background-color: #77ffff;text-align: center;line-height: 30px;color: #333;font-size: 12px;margin-right: 6px;}.msg_text {display: inline-block;padding: 4px 12px;border-radius: 6px;background-color: #f0f1dd;font-size: 14px;}.center_msg {text-align: center;color: #f19597;}.controls {width: 100%;display: flex;justify-content: space-between;margin-top: 10px;}input {flex: 1;outline: none;height: 34px;line-height: 34px;border: 1px solid #d8d8d8;border-radius: 4px;padding: 0 4px;color: #333;margin-right: 12px;}#btn {width: 80px;height: 34px;cursor: pointer;}</style></head><body><div class="main_container"><!-- 消息框 --><div id="msgList"></div><!-- 发送消息 --><div class="controls"><input type="text" class="pushMsg" /><button id="btn">发送</button></div></div><script src="./utils/websocket.js"></script><script>// 消息列表const msgList = [];// 初始化websocketconst newWebSocket = new WebSocketClient('ws:localhost:8080');newWebSocket.connect();window.NewWebSocket = newWebSocket;newWebSocket.addEventListener('message', handleMessage);// 处理返回数据function handleMessage(msg) {const msgData = JSON.parse(msg.data || '{}');console.log(msgData, "返回数据====");if (msgData && typeof msgData.msg === 'string' && !msgData.msg.includes('ping')) {msgList.push({name: msgData.nickname,msg: msgData.msg,});const str = msgList.reduce((cur, next) => {let curMsg = '';if (next.msg.includes('连接')) {curMsg = `<div class="center_msg">玩家:${next.name}_${next.msg}</div>`;} else {curMsg = `<div class="msg_line"><div class="avatar">${next.name}</div><div class="msg_text">${next.msg}</div></div>`;}return cur += curMsg;}, '');$('#msgList').html(str);// 获取设置了滚动属性的div标签const div = document.getElementById('msgList');// 设置滚动的顶点坐标为滚动的总高度div.scrollTop = div.scrollHeight;}}// 监听发送按钮$('#btn').on('click', sendMessage);// 输入框回车事件$('.pushMsg').keydown(function(event) {if (event.key === 'Enter') {sendMessage();}});// 发送消息function sendMessage() {const msg = $('.pushMsg').val();if (msg) {newWebSocket.send(`${msg}`);$('.pushMsg').val('');}}</script></body>
</html>
相关文章:
基于websocket与node搭建简易聊天室
一、前言 上一篇文章介绍了websocket的详细用法与工具类的封装,本篇就基于websocket搭建一个简易实时的聊天室。 在本篇开始之前也可以去回顾一下websocket详细用法:WebSocket详解与封装工具类 二、基于node搭建后台websocket服务 首先确认本机电脑中…...
DevOps全面综述:从概念到实践
一、背景与概述 1.1 DevOps的起源与发展 DevOps(Development and Operations的缩写)是软件工程领域中的一种文化和实践方法,旨在促进开发团队与运维团队之间的协作,从而实现更高效、更可靠的软件交付。DevOps起源于敏捷软件开发方…...
[C++]vector的模拟实现
下面是简单的实现vector的功能,没有涉及使用内存池等复杂算法来提高效率。 一、vector的概述 (一)、抽象数据类型定义 容器:向量(vector)vector是表示大小可以变化的数组的序列容器。像数组一样…...
【云原生】Kubernetes----POD控制器
目录 引言 一、Pod控制器概述 二、Pod控制器的种类 (一)ReplicaSet (二)Deployment (三)StatefulSet (四)DaemonSet (五)Job 三、使用POD控制器 &a…...
Java环境配置(超详细)
Java环境配置(超详细) 引言1、安装 JDK1.1、下载安装JDK1.2、配置环境变量:JAVA_HOME1.3、将JAVA_HOME添加到Path中 2、安装 Maven2.1、下载安装Maven2.2、配置maven的环境变量: M2_HOME2.3、将Maven变量添加到Path中 引言 Java开发环境的配…...
【操作系统】(详细理解进程的状态)执行状态、就绪状态、阻塞状态、挂起状态
下面是进程的几种状态的概念: 执行状态:当一个进程已获得必要资源,并占有CPU进行执行。 就绪状体:进程已分配到除CPU外的所有必要资源,只要获取CPU允许就可立即执行。 阻塞状态:正在执行的进程,…...
C++ -- string常用接口的底层实现
一.string介绍 1. string是表示字符串的字符串类,对C语言的字符串指针进行了包装。 2. 该类的接口与常规容器的接口基本相同,有增删查改等,再添加了一些专门用来操作string的常规操作。 二.成员变量 创建string类的时候要在自己的命名空间…...
怎么做好企业短信服务呢?(文字短信XML接口示例)
企业短信服务已经成为各行各业都信赖的行业推广方式之一,并且短信行业也与时俱进的发展着,随之而来的就是市场上短信平台的数量也随之增多。那么怎么在鱼龙混杂的短信行业中选择适合自己的企业短信服务平台呢?企业短信服务平台又适用于哪些应…...
鸿蒙小案例-音乐播放器
之前参加鸿蒙比赛的音乐播放器 效果展示 HF音乐效果展示 功能列 有一些功能没写上去,自行发掘 说明: 1.API:网易云接口,QQ个人接口, 需要请看gitee 2.本地关系型数据由bug,提的工单已确认,建议使用API11,12,9的不稳…...
语言模型测试系列【9】
语言模型 文心一言讯飞星火通义千问2.5豆包360智脑百小应腾讯元宝KimiC知道 好长时间没有做语言模型的测试了,一方面是没有好的素材,各模型都在升级优化,而且频率很高;另一方面近期在阅读和学习其他的知识,所以更的也…...
优思学院|质量工程师工资不高怎么办?
你是否曾经好奇,为什么在职场中,质量工程师的工资普遍不高?这一现象背后的原因,实际上与他们的职业门槛和专业知识密切相关。早期,国内的质量工程师入行门槛较低,许多人即使没有任何专业知识也可以进入这一…...
【面向就业的Liux基础】从入门到熟练,探索Linux的秘密(一)
主要帮助大家面向工作过程中Linux系统常用的命令联系,采用极致的实用主义,帮助大家节省时间。 文章目录 前言 一、linux系统 二、linux系统基本命令 1.Linux系统的目录结构 2. 常用命令介绍 3.命令演示 4.作业练习 总结 前言 主要帮助大家面向工作过程中…...
高效数据处理的前沿:【C++】、【Redis】、【人工智能】与【大数据】的深度整合
目录 1.为什么选择 C 和 Redis? 2.人工智能与大数据的背景 1.大数据的挑战 2.人工智能的需求 3.C 与 Redis 的完美结合 1.安装 Redis 和 Redis C 客户端 2.连接 Redis 并进行数据操作 高级数据操作 列表操作 哈希操作 4.与大数据和人工智能结合 5.实际应…...
Vitis HLS 学习笔记--控制驱动与数据驱动混合编程
目录 1. 简介 2. 示例分析 2.1 代码分析 2.2 控制驱动TLP的关键特征 2.3 数据驱动TLP的关键特征 3. 总结 1. 简介 在 HLS 硬件加速领域,Vitis HLS 提供了强大的抽象并行编程模型。这些模型包括控制驱动和数据驱动的任务级并行性(TLP)&…...
VUE3 学习笔记(12):对比Vuex与Pinia状态管理的基本理解
在组件传值中,当嵌套关系越来越复杂的时候必然会将混乱,是否可以把一些值存在一个公共位置,无须传值直接调用呢?VUEX应运而生,但是从VUE3开始对VUEX的支持就不那么高了,官方推荐使用Pinia。 Vuex配置 ST1:…...
区间预测 | Matlab实现QRCNN-BiGRU-Attention分位数回归卷积双向门控循环单元注意力机制时序区间预测
区间预测 | Matlab实现QRCNN-BiGRU-Attention分位数回归卷积双向门控循环单元注意力机制时序区间预测 目录 区间预测 | Matlab实现QRCNN-BiGRU-Attention分位数回归卷积双向门控循环单元注意力机制时序区间预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实…...
TypeScript算法每日一题:赎金信(383)
作者:前端小王hs 阿里云社区博客专家/清华大学出版社签约作者✍/CSDN百万访问博主/B站千粉前端up主 题库:力扣 题目序号:383(简单) 题目:赎金信 给你两个字符串ransomNote 和 magazine,判断ran…...
springboot 作为客户端接收服务端的 tcp 长连接数据,并实现自定义结束符,解决 粘包 半包 问题
博主最近的项目对接了部分硬件设备,其中有的设备只支持tcp长连接方式传输数据,博主项目系统平台作为客户端发起tcp请求到设备,设备接收到请求后作为服务端保持连接并持续发送数据到系统平台。 1.依赖引入 连接使用了netty,如果项…...
kuka编程怎么加中文:解锁KUKA机器人编程中的中文支持
kuka编程怎么加中文:解锁KUKA机器人编程中的中文支持 在工业自动化领域,KUKA机器人以其卓越的性能和广泛的应用而备受赞誉。然而,对于许多中国用户来说,如何在KUKA编程中加入中文支持却成为了一个挑战。本文将从四个方面、五个方…...
hadoop集群中zookeeper的搭建与原理解释
搭建zookeeper 将zookeeper的apache-zookeeper-3.5.7-bin.tar.gz解压到/export/servers下 tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz -C /export/servers为了方便后期使用解压后的文件夹改名为zookeeper-3.5.7 mv apache-zookeeper-3.5.7-bin zookeeper-3.5.7先进入zoo_…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...
[USACO23FEB] Bakery S
题目描述 Bessie 开了一家面包店! 在她的面包店里,Bessie 有一个烤箱,可以在 t C t_C tC 的时间内生产一块饼干或在 t M t_M tM 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC,tM≤109)。由于空间…...
VUE3 ref 和 useTemplateRef
使用ref来绑定和获取 页面 <headerNav ref"headerNavRef"></headerNav><div click"showRef" ref"buttonRef">refbutton</div>使用ref方法const后面的命名需要跟页面的ref值一样 const buttonRef ref(buttonRef) cons…...
Docker 镜像上传到 AWS ECR:从构建到推送的全流程
一、在 EC2 实例中安装 Docker(适用于 Amazon Linux 2) 步骤 1:连接到 EC2 实例 ssh -i your-key.pem ec2-useryour-ec2-public-ip步骤 2:安装 Docker sudo yum update -y sudo amazon-linux-extras enable docker sudo yum in…...
LeetCode第244题_最短单词距离II
LeetCode第244题:最短单词距离II 问题描述 设计一个类,接收一个单词数组 wordsDict,并实现一个方法,该方法能够计算两个不同单词在该数组中出现位置的最短距离。 你需要实现一个 WordDistance 类: WordDistance(String[] word…...
云原生技术驱动 IT 架构现代化转型:企业实践与落地策略全解
📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、背景:IT 架构演进的战略拐点 过去十年,企业 IT 架构经历了从传统集中式架构到分布式架构的转型。进入云计算…...
