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

node.js + html + Sealos容器云 搭建简易多人实时聊天室demo 带源码

node.js + html + Sealos容器云 搭建简易多人实时聊天室demo 带源码

  • 前言
    • 功能介绍(demo演示)
    • sealos官网配置
    • node.js 编写服务端代码
    • 前端ui + 调用接口
    • 整体项目目录
    • 部署到服务器

前言

hello哦盆友们,这次我们来十几行代码做一个超简单的多人聊天室,涉及功能不多,只是让大家熟悉娱乐一下,这次我们一切从简 使用到的技术为 node.js + html + sealos 云储存 * (sealos官方没给我打钱有官网人员看到了记得给打点。)

功能介绍(demo演示)

这是本地启动的服务,实现多人实时聊天的demo

多人实时聊天

在这里插入图片描述

sealos官网配置

sealos 云储存

由于我们聊天需要储存聊天记录等数据,所以这次使用了sealos云里面的 mongoDB 来储存我们的聊天数据, sealos云注册免费赠送我们额度,足够我们使用了,下面介绍一下sealos如何使用。

✨ 首先进入 sealos 云 官网 没有账户的注册一个账户,完成后登录我们点击极速体验按钮进入到工作台
✨ 进入到工作台后我们在下面找到数据库 如下图
在这里插入图片描述
✨ 进入到工作台后我们右上角选择新建 然后选择mongoDB 直接
在这里插入图片描述
在这里插入图片描述
✨ 这样我们就创建好了一个云的mogoDB储存啦 途中方框圈中的地方呆会儿我们在node服务里面要使用
在这里插入图片描述

node.js 编写服务端代码

✨ 首先我们在一个文件夹内初始化一个package.json 文件,我们这次使用到了 express框架 + socket.io + cors + mongoose 大家安装这几个依赖就可以了 复制到同学别忘了 npm install 一下哦

{"name": "chat-server","version": "1.0.0","description": "实时聊天服务器","main": "server.js","scripts": {"start": "node server.js","dev": "nodemon server.js"},"dependencies": {"express": "^4.17.1","socket.io": "^4.4.1","cors": "^2.8.5","mongoose": "^6.8.0"},"devDependencies": {"nodemon": "^2.0.15"}
} 

✨ 下面我们创建一个 server.js 功能作用我都给注释到代码层面了可自行研究

const express = require('express');
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http, {cors: {origin: '*', // 允许所有来源访问methods: ['GET', 'POST'],allowedHeaders: ['Content-Type'],credentials: true}
});
const cors = require('cors');
const mongoose = require('mongoose');const connectWithRetry = async () => {try {await mongoose.connect('这里替换成你的', {useNewUrlParser: true,useUnifiedTopology: true,serverSelectionTimeoutMS: 5000,socketTimeoutMS: 45000,});console.log('MongoDB 连接成功');} catch (err) {console.error('MongoDB 连接失败,5秒后重试:', err);setTimeout(connectWithRetry, 5000);}
};connectWithRetry();// 添加 MongoDB 连接错误处理
mongoose.connection.on('error', err => {console.error('MongoDB 连接错误:', err);
});mongoose.connection.on('disconnected', () => {console.log('MongoDB 连接断开');
});// 定义消息模型
const messageSchema = new mongoose.Schema({userId: String,username: String,content: String,timestamp: { type: Date, default: Date.now }
});const Message = mongoose.model('Message', messageSchema);// 启用 CORS
app.use(cors({origin: '*', // 允许所有来源访问,生产环境建议设置具体的域名methods: ['GET', 'POST'],allowedHeaders: ['Content-Type'],credentials: true
}));
app.use(express.json());// 存储在线用户
let onlineUsers = new Map();// Socket.IO 连接处理
io.on('connection', (socket) => {console.log('用户已连接');// 获取历史消息socket.on('getHistory', async () => {try {const messages = await Message.find().sort({ timestamp: -1 }).limit(50);  // 限制返回最近50条消息socket.emit('history', messages.reverse());} catch (err) {console.error('获取历史消息失败:', err);}});// 用户加入聊天socket.on('join', (userData) => {onlineUsers.set(socket.id, userData.username);io.emit('userList', Array.from(onlineUsers.values()));});// 处理消息发送socket.on('sendMessage', async (message) => {const messageData = {userId: socket.id,username: onlineUsers.get(socket.id),content: message,timestamp: new Date()};try {// 保存消息到数据库const newMessage = new Message(messageData);await newMessage.save();// 广播消息给所有客户端io.emit('message', messageData);} catch (err) {console.error('保存消息失败:', err);socket.emit('error', '消息发送失败');}});// 处理断开连接socket.on('disconnect', () => {onlineUsers.delete(socket.id);io.emit('userList', Array.from(onlineUsers.values()));console.log('用户已断开连接');});
});// 添加获取历史消息的 REST API
app.get('/api/messages', async (req, res) => {try {const page = parseInt(req.query.page) || 1;const limit = parseInt(req.query.limit) || 50;const messages = await Message.find().sort({ timestamp: -1 }).skip((page - 1) * limit).limit(limit);const total = await Message.countDocuments();res.json({messages: messages.reverse(),pagination: {current: page,limit,total}});} catch (err) {res.status(500).json({ error: '获取消息失败' });}
});// 基础路由
app.get('/', (req, res) => {res.send('聊天服务器正在运行');
});// 启动服务器
const PORT = process.env.PORT || 3000;
http.listen(PORT, () => {console.log(`服务器运行在端口 ${PORT}`);
}); 

前端ui + 调用接口

<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>实时聊天室</title><style>.chat-container {max-width: 800px;margin: 0 auto;padding: 20px;}.messages {height: 400px;border: 1px solid #ccc;overflow-y: auto;padding: 10px;margin-bottom: 20px;}.message {margin-bottom: 10px;padding: 5px;}.message .username {font-weight: bold;color: #2196F3;}.message .time {color: #999;font-size: 0.8em;}.input-area {display: flex;gap: 10px;}#messageInput {flex: 1;padding: 8px;}.user-list {border: 1px solid #ccc;padding: 10px;margin-bottom: 20px;}</style>
</head>
<body><div class="chat-container"><h2>实时聊天室</h2><div class="user-list"><h3>在线用户</h3><ul id="userList"></ul></div><div class="messages" id="messages"></div><div class="input-area"><input type="text" id="messageInput" placeholder="输入消息..."><button onclick="sendMessage()">发送</button></div></div><script src="https://cdn.socket.io/4.4.1/socket.io.min.js"></script><script>// 连接 Socket.IO 服务器const socket = io('http://localhost:3000');// 获取DOM元素const messagesDiv = document.getElementById('messages');const messageInput = document.getElementById('messageInput');const userList = document.getElementById('userList');// 生成随机用户名const username = '用户' + Math.floor(Math.random() * 1000);// 加入聊天socket.emit('join', { username });// 获取历史消息socket.emit('getHistory');// 监听历史消息socket.on('history', (messages) => {messages.forEach(message => {appendMessage(message);});scrollToBottom();});// 监听新消息socket.on('message', (message) => {console.log(message,"message");appendMessage(message);scrollToBottom();});// 监听用户列表更新socket.on('userList', (users) => {userList.innerHTML = users.map(user => `<li>${user}</li>`).join('');});// 发送消息function sendMessage() {const message = messageInput.value.trim();if (message) {socket.emit('sendMessage', message);messageInput.value = '';}}// 添加消息到界面function appendMessage(message) {const messageDiv = document.createElement('div');messageDiv.className = 'message';const time = new Date(message.timestamp).toLocaleTimeString();messageDiv.innerHTML = `<span class="username">${message.username}</span><span class="time">${time}</span><div class="content">${message.content}</div>`;messagesDiv.appendChild(messageDiv);}// 滚动到底部function scrollToBottom() {messagesDiv.scrollTop = messagesDiv.scrollHeight;}// 按回车发送消息messageInput.addEventListener('keypress', (e) => {if (e.key === 'Enter') {sendMessage();}});// 加载更多历史消息let currentPage = 1;async function loadMoreMessages() {try {const response = await fetch(`http://localhost:3000/api/messages?page=${currentPage}&limit=20`);const data = await response.json();data.messages.forEach(message => {const messageDiv = document.createElement('div');messageDiv.className = 'message';// ... 处理消息显示});currentPage++;} catch (error) {console.error('加载消息失败:', error);}}</script>
</body>
</html> 

整体项目目录

在这里插入图片描述

部署到服务器

这里大家自行部署到服务器就行,给你的好友展示一下。如果有需要部署教程的 等有时间出个部署教程

相关文章:

node.js + html + Sealos容器云 搭建简易多人实时聊天室demo 带源码

node.js html Sealos容器云 搭建简易多人实时聊天室demo 带源码 前言功能介绍&#xff08;demo演示&#xff09;sealos官网配置node.js 编写服务端代码前端ui 调用接口整体项目目录部署到服务器 前言 hello哦盆友们&#xff0c;这次我们来十几行代码做一个超简单的多人聊天…...

OpenFeign远程调用返回的是List<T>类型的数据

在使用 OpenFeign 进行远程调用时&#xff0c;如果接口返回的是 List 类型的数据&#xff0c;可以通过以下方式处理&#xff1a; 直接定义返回类型为List Feign 默认支持 JSON 序列化/反序列化&#xff0c;如果服务端返回的是 List的JSON格式数据&#xff0c;可以直接在 Feig…...

PCL 计算多边形的面积【2025最新版】

目录 一、算法原理1、概述2、主要函数3、函数源码二、代码实现三、结果展示博客长期更新,本文最近更新时间为:2025年1月17日。 一、算法原理 1、概述 根据给定的多边形的点云计算多边形的面积 A r e a = 1 2 ∑...

著名大模型评测榜单(不同评测方式)

在评估大语言模型的性能时&#xff0c;一种主流的途径就是选择不同的能力维度并且构建对应的评测任务&#xff0c;进而使用这些能力维度的评测任务对模型的性能进行测试与对比。由大型机构或者研究院所排出榜单。 评测指标 不同评测任务有不同的评指标&#xff0c;衡量模型的…...

国内知名Deepseek培训师培训讲师唐兴通老师讲授AI人工智能大模型实践应用

课程名称 《Deepseek人工智能大模型实践应用》 课程目标 全面了解Deepseek人工智能大模型的技术原理、功能特点及应用场景。 熟练掌握Deepseek大模型的提示词工程技巧&#xff0c;能够编写高质量的提示词。 掌握Deepseek大模型在办公、营销等领域的应用方法&#xff0c;提升…...

【AIGC】冷启动数据与多阶段训练在 DeepSeek 中的作用

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;冷启动数据的作用冷启动数据设计 &#x1f4af;多阶段训练的作用阶段 1&#xff1a;冷启动微调阶段 2&#xff1a;推理导向强化学习&#xff08;RL&#xff0…...

如何打造一个更友好的网站结构?

在SEO优化中&#xff0c;网站的结构往往被忽略&#xff0c;但它其实是决定谷歌爬虫抓取效率的关键因素之一。一个清晰、逻辑合理的网站结构&#xff0c;不仅能让用户更方便地找到他们需要的信息&#xff0c;还能提升搜索引擎的抓取效率 理想的网站结构应该像一棵树&#xff0c;…...

【ROS2】RViz2自定义面板插件(rviz_common::Panel)的详细步骤

【ROS】郭老二博文之:ROS目录 1、简述 RViz2 的插件基于 ROS2 的插件库(pluginlib)机制,通过动态加载共享库实现功能扩展。 注意:RViz2 使用 QT 作为 UI 框架,虽然 QT 也有插件机制,但是 RViz2 并没有使用QT的插件机制,而是通过 pluginlib 加载功能模块来实现。 2、…...

漏洞分析 Spring Framework路径遍历漏洞(CVE-2024-38816)

漏洞概述 VMware Spring Framework是美国威睿&#xff08;VMware&#xff09;公司的一套开源的Java、JavaEE应用程序框架。该框架可帮助开发人员构建高质量的应用。 近期&#xff0c;监测到Spring Framework在特定条件下&#xff0c;存在目录遍历漏洞&#xff08;网宿评分&am…...

《手札·避坑篇》2025年传统制造业企业数字化转型指南

一、引言 在数字化浪潮的推动下,传统制造业企业正加速向智能化、数字化转型。开源软件技术与制造MES(制造执行系统)产品的结合,为企业提供了高效、灵活且低成本的转型路径。本指南旨在为传统制造业企业的信息化负责人提供一套完整的数字化转型方案,助力企业实现高效、智能…...

MySQL中DDL操作是否支持事务

MySQL中DDL不支持事务。 传统MySQL&#xff08;5.7及以前版本&#xff09;&#xff1a; DDL操作不支持事务执行DDL操作时会隐式提交当前会话的事务无法回滚DDL操作 MySQL 8.0版本&#xff1a; 引入了原子DDL特性&#xff08;Atomic DDL&#xff09;DDL操作变为原子性的&…...

GWO优化决策树回归预测matlab

灰狼优化算法&#xff08;Grey Wolf Optimizer&#xff0c;简称 GWO&#xff09;是一种群智能优化算法&#xff0c;由澳大利亚格里菲斯大学的 Mirjalii 等人于 2014 年提出。该算法的设计灵感源自灰狼群体的捕食行为&#xff0c;核心思想是模仿灰狼社会的结构与行为模式。 在本…...

掌握Spring @SessionAttribute:跨请求数据共享的艺术

SessionAttribute注解在Spring中的作用&#xff0c;就像是一个“数据中转站”。 在Web应用中&#xff0c;我们经常需要在多个请求之间共享数据。比如&#xff0c;用户登录后&#xff0c;我们需要在多个页面或请求中保持用户的登录状态。这时&#xff0c;SessionAttribute注解就…...

python读取Excel表格内公式的值

背景&#xff1a;在做业务周报的时候&#xff0c;有一个Excel模板&#xff0c;表里面包含了一些公式&#xff0c;dataframe写入到Excel的时候&#xff0c;有公式的部分通过python读出来的结果是None&#xff0c;需要进行优化参考链接&#xff1a; 如何使用openpyxl读取Excel单元…...

第三十八章:阳江自驾之旅:挖蟹与品鲜

经历了惠州海边那趟温馨又欢乐的自驾之旅后&#xff0c;小冷和小颖心中对旅行的热情愈发高涨。闲暇时&#xff0c;两人总会坐在客厅里&#xff0c;翻看着旅行杂志&#xff0c;或是在网上搜索各地的美景&#xff0c;那些充满魅力的地方不断吸引着他们&#xff0c;也让他们对下一…...

C++小等于的所有奇数和=最大奇数除2加1的平方。

缘由 三种思路解题&#xff1a;依据算术推导得到一个规律&#xff1a;小等于的所有奇数和等于最大奇数除以2加1的平方。将在后续发布&#xff0c;总计有十种推导出来的实现代码。 int a 0,aa 1,aaa 0;cin >> a; while (aa<a) aaa aa, aa 2;cout << aaa;i…...

设置IDEA的内存大小,让IDEA更流畅: 建议设置在 2048 MB 及以上

文章目录 引言I 更改内存设置基于窗口界面进行内存设置修改内存配置文件II IDEA中的一些常见问题及其解决方案引言 方式一:基于窗口界面进行内存设置方式二:修改内存配置文件I 更改内存设置 基于窗口界面进行内存设置 打开IDEA,上方菜单栏 Help > Change Memory Settin…...

Ranger Hive Service连接测试失败问题解决

个人博客地址&#xff1a;Ranger Hive Service连接测试失败问题解决 | 一张假钞的真实世界 异常信息如下&#xff1a; org.apache.ranger.plugin.client.HadoopException: Unable to connect to Hive Thrift Server instance.. Unable to connect to Hive Thrift Server inst…...

车机音频参数下发流程

比如以audioControlWrapper.setParametersToAmp(keyPairValues); 下发banlance为例&#xff0c;链路如下 hal层 1. AudioControl.cpp hardware\interfaces\automotive\audiocontrol\aidl\default\AudioControl.cpp ndk::ScopedAStatus AudioControl::setParametersToAmp(co…...

大模型推理——MLA实现方案

1.整体流程 先上一张图来整体理解下MLA的计算过程 2.实现代码 import math import torch import torch.nn as nn# rms归一化 class RMSNorm(nn.Module):""""""def __init__(self, hidden_size, eps1e-6):super().__init__()self.weight nn.Pa…...

redis之GEO 模块

文章目录 背景GeoHash 算法redis中的GeoHash 算法基本使用增加距离获取元素位置获取元素的 hash 值附近的元素 注意事项原理 背景 如果我们有需求需要存储地理坐标&#xff0c;为了满足高性能的矩形区域算法&#xff0c;数据表需要在经纬度坐标加上双向复合索引 (x, y)&#x…...

21.2.7 综合示例

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 【例 21.7】【项目&#xff1a;code21-007】填充职员表并打印。 本例使用到的Excel文件为&#xff1a;职员信息登记表.xlsx&#x…...

使用Docker + Ollama在Ubuntu中部署deepseek

1、安装docker 这里建议用docker来部署&#xff0c;方便简单 安装教程需要自己找详细的&#xff0c;会用到跳过 如果你没有安装 Docker&#xff0c;可以按照以下步骤安装&#xff1a; sudo apt update sudo apt install apt-transport-https ca-certificates curl software-p…...

【C语言标准库函数】三角函数

目录 一、头文件 二、函数简介 2.1. 正弦函数&#xff1a;sin(double angle) 2.2. 余弦函数&#xff1a;cos(double angle) 2.3. 正切函数&#xff1a;tan(double angle) 2.4. 反正弦函数&#xff1a;asin(double value) 2.5. 反余弦函数&#xff1a;acos(double value)…...

CNN-day9-经典神经网络ResNet

day10-经典神经网络ResNet 1 梯度消失问题 深层网络有个梯度消失问题&#xff1a;模型变深时&#xff0c;其错误率反而会提升&#xff0c;该问题非过拟合引起&#xff0c;主要是因为梯度消失而导致参数难以学习和更新。 2 网络创新 2015年何凯明等人提出deep residual netw…...

淘宝分类详情数据获取:Python爬虫的高效实现

在电商领域&#xff0c;淘宝作为中国最大的电商平台之一&#xff0c;其分类详情数据对于市场分析、竞争对手研究以及电商运营优化具有不可估量的价值。通过Python爬虫技术&#xff0c;我们可以高效地获取这些数据&#xff0c;为电商从业者提供强大的数据支持。 一、为什么选择…...

机器学习 —— 深入剖析线性回归模型

一、线性回归模型简介 线性回归是机器学习中最为基础的模型之一&#xff0c;主要用于解决回归问题&#xff0c;即预测一个连续的数值。其核心思想是构建线性方程&#xff0c;描述自变量&#xff08;特征&#xff09;和因变量&#xff08;目标值&#xff09;之间的关系。简单来…...

33.日常算法

1.螺旋矩阵 题目来源 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5] class Solution { public:vec…...

#渗透测试#批量漏洞挖掘#微商城系统 goods SQL注入漏洞

免责声明 本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停止本文章读。 目录 一、漏洞概述 二、漏洞复现步骤 三、技术…...

【翻译+论文阅读】DeepSeek-R1评测:粉碎GPT-4和Claude 3.5的开源AI革命

目录 一、DeepSeek-R1 势不可挡二、DeepSeek-R1 卓越之处三、DeepSeek-R1 创新设计四、DeepSeek-R1 进化之路1. 强化学习RL代替监督微调学习SFL2. Aha Moment “啊哈”时刻3. 蒸馏版本仅采用SFT4. 未来研究计划 部分内容有拓展&#xff0c;部分内容有删除&#xff0c;与原文会有…...