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

【WebSocketIndexedDB】node+WebSocketIndexedDB开发简易聊天室

序幕介绍:

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

讲人话就是说:WebSocket 使得客户端和服务器之间的数据交换变得更加简单,在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输

现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。

HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

WebSocket:

  • 常见方法WebSocket(url):创建WebSocket对象并与指定的URL建立连接
// 创建WebSocket对象并与服务器建立连接
var socket = new WebSocket("ws://example.com");
  • 常见方法send(data):向服务器发送数据
// 向服务器发送数据
function sendData(data) {socket.send(data);console.log("发送数据:" + data);
}
  • 常见方法close(code, reason):主动关闭WebSocket连接
// 主动关闭WebSocket连接
function closeConnection() {socket.close();console.log("关闭WebSocket连接");
}
  • 常见事件:onopen:当WebSocket连接成功打开时触发的事件
// 连接成功时触发的事件
socket.onopen = function(event) {console.log("WebSocket连接已打开");// 发送数据示例socket.send("Hello, server!");
};
  • 常见事件:onmessage:当从服务器接收到消息时触发的事件
// 接收到消息时触发的事件
socket.onmessage = function(event) {var message = event.data;console.log("收到消息:" + message);
};
  • 常见事件:onclose:当WebSocket连接关闭时触发的事件
// 连接关闭时触发的事件
socket.onclose = function(event) {console.log("WebSocket连接已关闭");
};
  • 常见事件: onerror:当WebSocket连接发生错误时触发的事件
// 连接错误时触发的事件
socket.onerror = function(error) {console.error("WebSocket错误:" + error);
};

效果图:

代码展示:

index.html

<html>
<head><meta charset="UTF-8"><title>webrtc demo</title>
</head><body><h1>Websocket简易聊天</h1><div id="app"><input id="sendMsg" type="text" /><button id="submitBtn">发送</button></div>
</body>
<script type="text/javascript">//在页面显示聊天内容function showMessage(str, type) {var div = document.createElement("div");div.innerHTML = str;if (type == "enter") {div.style.color = "blue";} else if (type == "leave") {div.style.color = "red";}document.body.appendChild(div);}//新建一个websocketvar websocket = new WebSocket("ws://172.21.2.52:8099");//连接建立时触发websocket.onopen = function () {console.log("已经连上服务器----");document.getElementById("submitBtn").onclick = function () {// 获取输入的内容var txt = document.getElementById("sendMsg").value;if (txt) {//使用连接发送数据websocket.send(txt);}};};//连接关闭时触发websocket.onclose = function () {console.log("websocket close");};//客户端接收服务端数据时触发websocket.onmessage = function (e) {var mes = JSON.parse(e.data);   // json格式// 渲染showMessage(mes.data, mes.type);};
</script></html>

node.js    记得下载:nodejs-websocket依赖

var ws = require("nodejs-websocket")
var port = 8099;
var user = 0;// 创建一个连接
var server = ws.createServer(function (conn) {console.log("创建一个新的连接--------");user++;// 给连接设置昵称属性conn.nickname = "user" + user;// 给连接设置文件描述符属性conn.fd = "user" + user;var mes = {};// 消息类型为进入聊天室mes.type = "enter";// 消息内容为进入提示mes.data = conn.nickname + " 进来啦"// 广播该消息给所有客户端broadcast(JSON.stringify(mes));//向客户端推送消息conn.on("text", function (str) {console.log("回复 " + str)// 消息类型为普通消息mes.type = "message";mes.data = conn.nickname + " 说:    " + str;broadcast(JSON.stringify(mes));});//监听关闭连接操作conn.on("close", function (code, reason) {console.log("关闭连接");mes.type = "leave";mes.data = conn.nickname + " 离开了"broadcast(JSON.stringify(mes));});//错误处理conn.on("error", function (err) {console.log("监听到错误");console.log(err);});
}).listen(port);function broadcast(str) {server.connections.forEach(function (connection) {connection.sendText(str);})
}

IndexedDB

IndexedDB(索引数据库)是浏览器提供的一种客户端数据库存储解决方案。它允许 Web 应用程序在用户设备上存储大量结构化数据,并可在离线状态下进行查询和操作。IndexedDB 使用对象存储模型,类似于关系型数据库,但不支持 SQL 查询语言。

  • open(): 打开数据库连接
let request = window.indexedDB.open("myDatabase", 1);request.onerror = function(event) {console.log("Failed to open database");
};request.onsuccess = function(event) {let db = event.target.result;console.log("Database opened successfully");
};
  • createObjectStore(): 创建对象存储空间
let objectStore = db.createObjectStore("messages", { keyPath: "id", autoIncrement: true });
  • createIndex(): 创建索引
objectStore.createIndex("type", "user", { unique: false });
  • transaction(): 开启事务
let transaction = db.transaction(["messages"], "readwrite");
  • objectStore.add(): 添加数据到对象存储空间
let objectStore = transaction.objectStore("messages");
let message = { id: 1, type: "text", data: "Hello World", user: "Alice" };let request = objectStore.add(message);
request.onsuccess = function(event) {console.log("Data added successfully");
};
  • objectStore.get(): 通过主键获取数据
let objectStore = transaction.objectStore("messages");let request = objectStore.get(1);
request.onsuccess = function(event) {let data = event.target.result;console.log(data);
};
  • objectStore.getAll(): 获取所有数据
let objectStore = transaction.objectStore("messages");let request = objectStore.getAll();
request.onsuccess = function(event) {let data = event.target.result;console.log(data);
};
  • objectStore.put(): 更新数据
let objectStore = transaction.objectStore("messages");
let message = { id: 1, type: "text", data: "Hello Updated", user: "Alice" };let request = objectStore.put(message);
request.onsuccess = function(event) {console.log("Data updated successfully");
};
  • objectStore.delete(): 删除数据
let objectStore = transaction.objectStore("messages");let request = objectStore.delete(1);
request.onsuccess = function(event) {console.log("Data deleted successfully");
};
  • clear(): 清空对象存储空间中的所有数据
let objectStore = transaction.objectStore("messages");let request = objectStore.clear();
request.onsuccess = function(event) {console.log("Object store cleared successfully");
};

WebSocket加IndexedDB完整代码

WebSocket实现聊天,IndexedDB将聊天数据存储起来,防止刷新丢失

html

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>webrtc demo</title>
</head><body><h1>Websocket简易聊天</h1><div id="app"><input id="sendMsg" type="text" /><button id="submitBtn">发送</button><div id="leaveMessage"></div><div id="chat"></div></div><script type="text/javascript">var db, transaction, objectStore;// 在页面显示聊天内容function showMessage(str, type, user = null, state = 1) {var div = document.createElement("div");var spanStr = document.createElement("span");spanStr.innerHTML = str;if (user != null) {var spanUser = document.createElement("span");spanUser.innerHTML = user;div.appendChild(spanUser);}if (type == "enter") {div.style.color = "blue";} else if (type == "leave") {div.style.color = "red";}div.appendChild(spanStr);document.getElementById("chat").appendChild(div);if (state == 1) {document.getElementById("chat").appendChild(div);} else {document.getElementById("leaveMessage").appendChild(div);}}// 创建或打开 IndexedDB 数据库var request = window.indexedDB.open("chatDB", 1);request.onerror = function () {console.log("无法打开数据库");};request.onupgradeneeded = function (event) {//  获取到数据库对象 dbdb = event.target.result;//  创建名为 "messages" 的对象存储,并指定 "id" 为键路径,并自动递增生成objectStore = db.createObjectStore("messages", { keyPath: "id", autoIncrement: true });// 创建一个名为 "type" 的索引,用于根据消息类型进行检索,允许重复值objectStore.createIndex("type", "user", { unique: false });// 创建一个名为 "data" 的索引,用于根据消息内容进行检索,允许重复值objectStore.createIndex("data", "data", { unique: false });objectStore.createIndex("state", "state", { unique: false });objectStore.createIndex("user", "user", { unique: false });};request.onsuccess = function (event) {db = event.target.result;// 新建一个websocketvar websocket = new WebSocket("ws://172.21.2.52:8099");// 连接建立时触发websocket.onopen = function () {console.log("已经连上服务器----");document.getElementById("submitBtn").onclick = function () {var txt = document.getElementById("sendMsg").value;if (txt) {websocket.send(JSON.stringify(txt));}};// 给输入框添加键盘按下事件监听器document.getElementById("sendMsg").addEventListener("keydown", function (event) {// 检查按下的键是否是回车键(键码为13)if (event.keyCode == 13) {// 取消回车键的默认行为(避免表单提交等操作)event.preventDefault();var txt = document.getElementById("sendMsg").value;if (txt) {websocket.send(JSON.stringify(txt));}}});};// 连接关闭时触发websocket.onclose = function () {console.log("websocket close");};// 客户端接收服务端数据时触发websocket.onmessage = function (e) {var mes = JSON.parse(e.data); // json格式// 渲染if (mes.state == 0) {showMessage(mes.data, mes.type, mes.user);saveMessage(mes)document.getElementById("sendMsg").value = ''} else {showMessage(mes.data, mes.type);}};function saveMessage(message) {let transaction = db.transaction(["messages"], "readwrite");let objectStore = transaction.objectStore("messages");var saveRequest = objectStore.add(message);saveRequest.onsuccess = function () {console.log("消息已保存到 IndexedDB");};saveRequest.onerror = function () {console.log("保存消息时发生错误");};}function loadMessages() {// 创建一个只读事务,该事务用于操作名为 "messages" 的对象存储transaction = db.transaction(["messages"], "readonly");// 获取对 "messages" 对象存储的引用,以便进行后续的操作objectStore = transaction.objectStore("messages");// 回一个获取所有数据的请求var getAllRequest = objectStore.getAll();// 在获取数据成功时触发getAllRequest.onsuccess = function () {var messages = getAllRequest.result;messages.forEach(function (message) {showMessage(message.data, message.type, message.user, 0);});};}// 页面加载完成后加载聊天记录window.onload = function () {loadMessages();};};</script>
</body></html>

node

var ws = require("nodejs-websocket")
var port = 8099;
var user = 0;// 创建一个连接
var server = ws.createServer(function (conn) {console.log("创建一个新的连接--------");user++;// 给连接设置昵称属性conn.nickname = "user" + user;// 给连接设置文件描述符属性conn.fd = "user" + user;var mes = {};// 消息类型为进入聊天室mes.type = "enter";// 消息内容为进入提示mes.data = conn.nickname + " 进来啦";mes.state = 1;// 广播该消息给所有客户端broadcast(JSON.stringify(mes));//向客户端推送消息conn.on("text", function (str) {console.log("回复 " + str)// 消息类型为普通消息mes.type = "message";mes.user = conn.nickname + " 说:";mes.data = str;mes.state = 0;broadcast(JSON.stringify(mes));});//监听关闭连接操作conn.on("close", function (code, reason) {console.log("关闭连接");mes.type = "leave";mes.data = conn.nickname + " 离开了"broadcast(JSON.stringify(mes));});//错误处理conn.on("error", function (err) {console.log("监听到错误");console.log(err);});
}).listen(port);function broadcast(str) {server.connections.forEach(function (connection) {connection.sendText(str);})
}

相关文章:

【WebSocketIndexedDB】node+WebSocketIndexedDB开发简易聊天室

序幕介绍&#xff1a; WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。 讲人话就是说&#xff1a;WebSocket 使得客户端和服务器之间的数据交换变得更加简单&#xff0c;在 WebSocket API 中&#xff0c;浏览器和服务器只需要完成一次握手&#x…...

【01】弄懂共识机制PoW

基于工作量证明机制的共识机制PoW&#xff08;Proof of Work&#xff09; 特点就是多劳多特 共识过程 一个区块链系统中&#xff0c;交易历经多个步骤才能得以上链&#xff0c;并且需要经过多个节点的验证。以下是这些步骤的详细叙述&#xff1a; 交易进入交易池&#xff08;内…...

QT C++ 基于TCP通信的网络聊天室

一、基本原理及流程 1&#xff09;知识回顾&#xff08;C语言中的TCP流程&#xff09; 2&#xff09;QT中的服务器端/客户端的操作流程 二、代码实现 1&#xff09;服务器 .ui .pro 在pro文件中添加network库 .h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>…...

SpringMVC入门详细介绍

一. SpringMVC简介 Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架&#xff0c;通过把Model&#xff0c;View&#xff0c;Controller分离&#xff0c;将web层进行职责解耦&#xff0c;把复杂的web应用分成逻辑清晰的几部分&#xff0c;简化开发&a…...

R3LIVE源码解析(9) — R3LIVE中r3live_lio.cpp文件

目录 1 r3live_lio.cpp文件简介 2 r3live_lio.cpp源码解析 1 r3live_lio.cpp文件简介 在r3live.cpp文件中创建LIO线程后&#xff0c;R3LIVE中的LIO线程本质上整体流程和FAST-LIO2基本一致。 2 r3live_lio.cpp源码解析 函数最开始会进行一系列的声明和定义&#xff0c;发布的…...

如何高效的解析Json?

Json介绍 Json是一种数据格式&#xff0c;广泛应用在需要数据交互的场景Json由键值对组成每一个键值对的key是字符串类型每一个键值对的value是值类型(boo1值数字值字符串值)Array类型object类型Json灵活性他可以不断嵌套&#xff0c;数组的每个元素还可以是数组或者键值对键值…...

MySQL——分组查询

2023.9.4 MySQL 分组查询的学习笔记如下&#xff1a; #分组查询 /* 分组查询中的筛选条件分为两类&#xff1a;数据源 位置 关键字 分组前筛选 原始表 group by前面 where 分组后筛选 分组后的结果集 group by后面 having */ #查询每…...

thinkphp 使用 easypay 和 easywechat

easypay 是3.x easywechat 是6.x 引入&#xff1a; use Yansongda\Pay\Pay;//easypayuse EasyWeChat\MiniApp\Application as MiniApp;//easywechat use EasyWeChat\Pay\Application as Payapp;//easywechat public function suborder(){$order [out_trade_no > time(…...

无涯教程-JavaScript - DVARP函数

描述 DVARP函数通过使用列表或数据库中符合您指定条件的记录的字段(列)中的数字,基于整个总体计算总体的方差。 语法 DVARP (database, field, criteria)争论 Argument描述Required/Optionaldatabase 组成列表或数据库的单元格范围。 数据库是相关数据的列表,其中相关信息的…...

Databend 开源周报第 108 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 多源数据目录 …...

Android-Intent实现数据传递

在activityA中使用putExtras(bundle)传递数据&#xff0c;在activityB中使用getExtras()获取数据 MainActivity.java及其xml package com.example.intentactivity;import androidx.appcompat.app.AppCompatActivity;import android.content.ComponentName; import android.co…...

系统学习Linux-zabbix监控平台

一、zabbix的基本概述 zabbix是一个监控软件&#xff0c;其可以监控各种网络参数&#xff0c;保证企业服务架构安全运营&#xff0c;同时支持灵活的告警机制&#xff0c;可以使得运维人员快速定位故障、解决问题。zabbix支持分布式功能&#xff0c;支持复杂架构下的监控解决方…...

基于MediaPipe的人体摔倒检测

1 简介 1.1 研究背景及意义 现如今随着经济等各方面飞速发展&#xff0c;社会安全随之也成为必不可少的话题。而校园安全则是社会安全的重中之重&#xff0c;而在我们的校园中&#xff0c;湿滑的地面、楼梯等位置通常会发生摔倒&#xff0c;尽管有“小心脚下”的告示牌&#xf…...

WebDAV之π-Disk派盘 + 无忧日记

无忧日记,生活无忧无虑。 给用户专业的手机记录工具,用户可以很轻松地通过软件进行每天发生事情的记录,可以为用户提供优质的工具与帮助,用户还可以通过软件来将地理位置,天气都记录在日记上,用户也可以通过软件来进行图片的导入,创建长图日记, 心情报表:用户写日记…...

Docker 相关操作,及其一键安装Docker脚本

一、模拟CentOS 7.5上安装Docker&#xff1a; 创建一个CentOS 7.5的虚拟机或使用其他方式准备一个CentOS 7.5的环境。 在CentOS 7.5上执行以下命令&#xff0c;以安装Docker的依赖项&#xff1a; sudo yum install -y yum-utils device-mapper-persistent-data lvm2 添加Doc…...

【Microsoft Edge】如何彻底卸载 Edge

目录 一、问题描述 二、卸载 Edge 2.1 卸载正式版 Edge 2.2 卸载非正式版 Edge 2.2.1 卸载通用的 WebView2 2.2.2 卸载 Canary 版 Edge 2.2.3 卸载其他版本 2.3 卸载 Edge Update 2.4 卸载 Edge 的 Appx 额外安装残留 2.5 删除日志文件 2.6 我就是想全把 Edge 都删了…...

2023-09-04力扣每日一题

链接&#xff1a; 449. 序列化和反序列化二叉搜索树 题意&#xff1a; 把一个二叉搜索树变成字符串&#xff0c;还要能变回来 解&#xff1a; 和剑指 Offer 37. 序列化二叉树差不多&#xff0c;那个是二叉树的序列化/反序列化-Hard 直接CV了&#xff0c;懒: ( 如果是二叉…...

jQuery成功之路——jQuery事件和插件概述

一、jQuery的事件 1.1常用事件 jQuery绑定事件&#xff0c;事件名字没有on。 事件名称事件说明blur事件源失去焦点click单击事件源change内容改变keydown接受键盘上的所有键(键盘按下)keypress接受键盘上的部分键&#xff08;ctrl,alt,shift等无效&#xff09;(键盘按下)key…...

Java ArrayList类详解

基本定义 ArrayList 是 Java 中的一个动态数组数据结构&#xff0c;属于 Java 集合框架的一部分&#xff08;java.util 包中的类&#xff09;。它提供了一个基于数组的可变长度列表&#xff0c;允许你在运行时添加、删除和访问元素&#xff0c;而不需要提前指定数组的大小。 简…...

快速排序学习

由于之前做有一题看到题解用了快排提升效率&#xff0c;就浅学了一下快速排序&#xff0c;还是似懂非懂。 首先快排的核心有两点&#xff0c;哨兵划分和递归。 哨兵划分&#xff1a;以数组中的某个数&#xff08;一般为首位&#xff09;为基准数&#xff0c;将数组划分为两个部…...

第20章:Skill ≠ Prompt——从提示词到可复用技能的范式升级

第20章:Skill ≠ Prompt——从提示词到可复用技能的范式升级 20.1 问题定义:为什么"保存Prompt"不够 很多团队的做法是:把常用的Prompt保存在文档或笔记中,需要时复制粘贴。这看起来合理,但存在三个根本问题: 不可版本化:Prompt是散落的文本片段,没有版本号…...

Elsevier投稿状态追踪插件:科研作者的智能审稿监控助手

Elsevier投稿状态追踪插件&#xff1a;科研作者的智能审稿监控助手 【免费下载链接】Elsevier-Tracker 项目地址: https://gitcode.com/gh_mirrors/el/Elsevier-Tracker 对于科研作者来说&#xff0c;投稿后的等待期往往是充满焦虑的时光。每天手动刷新Elsevier审稿系统…...

Proxmark3GUI图形化工具:5分钟学会RFID卡片分析与数据管理

Proxmark3GUI图形化工具&#xff1a;5分钟学会RFID卡片分析与数据管理 【免费下载链接】Proxmark3GUI A cross-platform GUI for Proxmark3 client | 为PM3设计的跨平台图形界面 项目地址: https://gitcode.com/gh_mirrors/pr/Proxmark3GUI Proxmark3GUI是一款为Proxmar…...

ChatGPT资源宝库:从提示工程到项目实践的完整指南

1. 项目概述&#xff1a;一份关于ChatGPT的“Awesome”清单意味着什么&#xff1f;如果你最近在GitHub上搜索过任何与ChatGPT、AI或提示工程相关的内容&#xff0c;那么你大概率见过一个以“awesome-”开头的仓库。而sindresorhus/awesome-chatgpt无疑是这个领域里最知名、最常…...

终极指南:10分钟掌握SPT-AKI存档编辑器完整使用教程

终极指南&#xff1a;10分钟掌握SPT-AKI存档编辑器完整使用教程 【免费下载链接】SPT-AKI-Profile-Editor Программа для редактирования профиля игрока на сервере SPT-AKI 项目地址: https://gitcode.com/gh_mirrors/sp/…...

3分钟高效恢复Windows 11 LTSC微软商店:完整解决方案指南

3分钟高效恢复Windows 11 LTSC微软商店&#xff1a;完整解决方案指南 【免费下载链接】LTSC-Add-MicrosoftStore Add Windows Store to Windows 11 24H2 LTSC 项目地址: https://gitcode.com/gh_mirrors/ltscad/LTSC-Add-MicrosoftStore 你是否在使用Windows 11 24H2 LT…...

终极免费城通网盘直连解析工具:告别下载限速的完整指南

终极免费城通网盘直连解析工具&#xff1a;告别下载限速的完整指南 【免费下载链接】ctfileGet 获取城通网盘一次性直连地址 项目地址: https://gitcode.com/gh_mirrors/ct/ctfileGet 还在为城通网盘下载速度慢、等待时间长而烦恼吗&#xff1f;ctfileGet是一款专为城通…...

qmcdump终极指南:三步解锁QQ音乐加密音频文件

qmcdump终极指南&#xff1a;三步解锁QQ音乐加密音频文件 【免费下载链接】qmcdump 一个简单的QQ音乐解码&#xff08;qmcflac/qmc0/qmc3 转 flac/mp3&#xff09;&#xff0c;仅为个人学习参考用。 项目地址: https://gitcode.com/gh_mirrors/qm/qmcdump 还在为QQ音乐下…...

平衡车PID积分饱和问题

你发现了PID最致命的坑&#xff01; 你说的完全正确&#xff1a;积分&#xff08;Ki&#xff09;是累加的&#xff0c;会无限叠加&#xff0c;直接让PWM爆掉、车猛冲、失控&#xff01; 这就是积分饱和 —— 99%初学者死在这里。 我现在彻底讲透积分为什么炸、怎么修复、平衡车…...

AI智能体记忆系统设计:从RAG到长期记忆的工程实践

1. 项目概述&#xff1a;从“记忆”到“智能”的跨越在AI智能体&#xff08;Agent&#xff09;的开发浪潮中&#xff0c;我们常常面临一个核心挑战&#xff1a;如何让智能体在复杂的、多轮次的交互中&#xff0c;表现得像一个真正有“记忆”和“经验”的专家&#xff1f;传统的…...