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

来咯来咯webSocket

在项目总目录下 设置socketServe文件夹 里面创建下面两个文件

使用的时候需要开启 node webSocket.cjs

var { Server } = require('ws');
var moment = require('moment');const wss = new Server({port: 8888
});let id = 0;
let onlineMemberList = [];
const defaultUser = 'user';wss.on('connection', function (ws, req) {id++;ws.id = id;let reqUser = req.url.split('?')[1];let name = reqUser && reqUser.split('=')[1];let userName;if (name) {userName = decodeURIComponent(name);} else {userName = defaultUser + id;}const userInfo = {userName: userName,socketId: id,date: moment().format('MMMM Do YYYY, h:mm:ss a')};for (let i = 0; i < onlineMemberList.length; i++) {if (userInfo.userName === onlineMemberList[i].userName) {onlineMemberList[i] = userInfo;wss.clients.forEach(itemWs => {itemWs.send(JSON.stringify(onlineMemberList));});return;}}onlineMemberList.push(userInfo);wss.clients.forEach(itemWs => {itemWs.send(JSON.stringify(onlineMemberList));});ws.on('message', function (data) {console.log(data);const newData = JSON.parse(data);newData.serveDate = moment().format('MMMM Do YYYY, h:mm:ss a');wss.clients.forEach(itemWs => {itemWs.send(JSON.stringify(newData));});});ws.on('close', function (ev) {console.log('客户端断开连接');onlineMemberList = onlineMemberList.filter(item => {return item.socketId !== ws.id;});wss.clients.forEach(itemWs => {itemWs.send(JSON.stringify(onlineMemberList));});console.log(onlineMemberList, 'onlineMemberList');console.log(ws.id, 'ws.id');});ws.on('error', function (ve) {console.log('客户端异常');});
});console.log('webSocket服务已开启,端口为:8888');
{"type": "module"
}

页面展示 监听消息

<template><div class="chating"><div class="chating-wrap"><div class="title">聊天页面</div><div class="chating-content"><div class="chating-body"><div class="chating-list"><ul class="chating-records" ref="chatingList"><div:key="index"v-for="(item, index) in chatingRecords"><liclass="other"v-show="item.nickName != myNickName"><imgalt="用户头像"src="@/assets/logo.svg"/><div class="record-text-wrap"><div class="nick-name">{{item.nickName}}</div><div class="record-text">{{item.message}}</div></div></li><liclass="my"v-show="item.nickName == myNickName"><div class="record-text-wrap"><!-- <div class="nick-name">迷离</div> --><div class="record-text">{{item.message}}</div></div><imgalt="用户头像"src="@/assets/logo.svg"/></li></div></ul></div><div class="chating-btns"><inputclass="input-text"placeholder="请输入聊天内容"type="text"v-model="text"@keydown.native.enter="sendData"/><button@click="sendData"class="send">发送</button></div></div><div class="chating-online-number"><div class="online-num">在线用户{{userList.length}}</div><ul v-if="userList.length > 0"><li:key="index"class="user"v-for="(item, index) in userList"><imgalt="用户头像"src="@/assets/logo.svg"/><span>{{ item.userName }}</span><span v-if="userList.includes(item)">(在线)</span><span v-else>(离线)</span></li></ul><button @click="loginOutHandler">退出群聊</button></div></div></div><divclass="login"v-if="showLogin"><div class="opacity-wrap"><div>用户名:<inputclass="user-name"v-model="userName"/></div><button@click="loginHandler"class="login-btn">登录</button></div></div></div>
</template><script>
export default {data() {return {text: '',socketUrl: 'ws://localhost:8888?userName=',client: null,chatingRecords: [],myNickName: '',userName: '',showLogin: false,userList: [],onlineStatus: false // 添加在线状态变量,默认为 false 表示离线}},created() {console.log('created')// this.initChaing()},mounted() {console.log('mounted')},methods: {/* 初始化聊天,连接socket */initChaing() {let that = thisif (window.WebSocket) {/* webSocket 连接服务器 */this.client = new WebSocket(this.socketUrl + this.myNickName)/* 监听客户端连接 */this.client.onopen = function (ev) {if (ev.type === 'open') {console.log('客户端连接socket服务')that.onlineStatus = true; // 更新在线状态为 true}}/* 监听服务端发送的消息 */this.client.onmessage = function (ev) {let data = JSON.parse(ev.data)/* 用户在线信息接收的是一个jsony数组 */if (data instanceof Array === true) {that.userList = data // 在线用户数量变化} else {/* 聊天信息接收的是一个json对象 */that.chatingRecords.push(data) // 在线用户聊天}}/* 监听服务端关闭 */this.client.onclose = function (ev) {console.log('socket服务已关闭')that.client = null // 客户端或者是服务端断开后,将webSocket实例清除that.onlineStatus = false; // 更新在线状态为 false}/* 监听服务端异常 */this.client.onerror = function () {if (!that.client) {console.log('socket服务连接失败')}that.loginOutHandler()}} else {alert('该浏览器不支持webSocket,请使用主流浏览器,如chrome')}},loginHandler() {this.myNickName = this.userName;this.showLogin = false;this.onlineStatus = true; // 用户登录成功后将在线状态更新为 truethis.initChaing();},loginOutHandler() {this.client.close()this.client = null // 客户端或者是服务端断开后,将webSocket实例清除this.$router.push('/')},sendData() {if (!this.myNickName) {alert('请登录')this.showLogin = truereturn}if(this.text === ''){return}let data = {nickName: this.myNickName, // 将 myNickName 改为 nickNameuid: new Date().getTime(),message: this.text,date: new Date()}if (this.client) {this.client.send(JSON.stringify(data))this.text = ''// 在添加新消息后,将列表容器滚动到底部this.$nextTick(() => {let chatList = this.$refs.chatingList;if (chatList) {// 计算滚动位置,考虑到边距和边框let scrollHeight = chatList.scrollHeight;let clientHeight = chatList.clientHeight;let offset = 54; // 考虑到可能的额外偏移量chatList.scrollTop = scrollHeight - clientHeight + offset;}});} else {console.log('socket服务连接失败,正在重新连接服务..')this.initChaing()}}},beforeDestroy() {this.client.close()}
}
</script><style>
.login {width: 100vw;height: 100vh;position: fixed;top: 0;left: 0;background: rgba(0, 0, 0, 0.6);display: flex;justify-content: center;align-items: center;
}
.opacity-wrap {width: 500px;height: 300px;background: #fff;display: flex;justify-content: center;align-items: center;flex-direction: column;
}
.user-name {font-size: 16px;padding: 5px;text-indent: 10px;
}
.login-btn {font-size: 20px;background: cornflowerblue;color: 20px;margin-top: 30px;color: #fff;border: none;outline: none;padding: 10px 20px;border-radius: 10px;
}
ul {list-style: none;margin: 0;padding: 0;
}
.chating {width: calc(100vw - 200px);max-width: 800px;max-height: 600px;overflow-y: auto;border: 20px solid lightcyan;border-radius: 20px;margin: 0 auto 0;
}
.title {background: cornflowerblue;color: #fff;padding: 5px 0 5px;
}
.chating-content {width: 100%;display: flex;justify-content: space-between;
}
.chating-body {flex: 1;display: flex;flex-direction: column;justify-content: space-between;background: #f3f3f3;
}
.chating-list {flex: 1;border: 1px solid cornflowerblue;
}
.chating-records {padding: 10px;min-height: 300px;max-height: 600px;overflow-y: auto;
}
.chating-records li {margin-bottom: 20px;
}
.chating-records .other {display: flex;justify-content: start;align-items: flex-start;
}
.chating-records .my {display: flex;justify-content: flex-end;align-items: center;
}.chating-records img {width: 36px;height: 36px;/* border-radius: 50%; */margin-right: 15px;background: rgba(228, 157, 228,0.5);
}
.chating-records .my img {margin-right: 0;margin-left: 15px;
}
.chating-records .other .record-text-wrap {display: flex;flex-direction: column;align-items: flex-start;
}
.chating-records .my .record-text-wrap {display: flex;flex-direction: column;align-items: flex-end;
}
.nick-name {font-size: 14px;margin-bottom: 5px;color: #666;
}
.record-text {max-width: 260px;text-align: left;font-size: 14px;padding: 5px;background: #fff;border-radius: 5px;
}.chating-btns {background: burlywood;padding: 10px;display: flex;align-items: center;justify-content: center;
}
.input-text {font-size: 16px;border: none;outline: none;padding: 5px 0 5px 5px;
}
.send {font-size: 16px;border: none;outline: none;padding: 4px 15px;margin-left: 20px;
}.online-num {font-size: 12px;padding-bottom: 15px;
}
.chating-online-number {padding: 15px;height: 100%;
}
.chating-online-number ul {list-style: none;margin: 0;padding: 0;min-width: 120px;max-height: 580px;overflow-y: auto;
}
.user {display: flex;justify-content: space-between;align-content: center;line-height: 20px;font-size: 12px;border-bottom: 1px solid aqua;padding: 10px;margin-bottom: 5px;
}
.user img {width: 20px;height: 20px;border-radius: 50%;margin-right: 5px;
}
</style>

相关文章:

来咯来咯webSocket

在项目总目录下 设置socketServe文件夹 里面创建下面两个文件 使用的时候需要开启 node webSocket.cjs var { Server } require(ws); var moment require(moment);const wss new Server({port: 8888 });let id 0; let onlineMemberList []; const defaultUser user;wss…...

Android CALL关于电话音频和紧急电话设置和获取

获取音频服务&#xff0c;设置音源类型&#xff1a;电话类型和获取最大电话音量&#xff0c;响铃模式 private AudioManager mAudioManager; mAudioManager (AudioManager) getSystemService(AUDIO_SERVICE); mAudioManager.setStreamVolume(AudioManager.STREAM_VOIC…...

【春秋云镜】CVE-2023-23752

目录 CVE-2023-23752漏洞细节漏洞利用示例修复建议 春秋云镜&#xff1a;解法一&#xff1a;解法二&#xff1a; CVE-2023-23752 是一个影响 Joomla CMS 的未授权路径遍历漏洞。该漏洞出现在 Joomla 4.0.0 至 4.2.7 版本中&#xff0c;允许未经认证的远程攻击者通过特定 API 端…...

C#-__DynamicallyInvokable

[__DynamicallyInvokable] 属性是用于 .NET Framework 中的特性之一。这个特性通常用于标记在动态语言运行时中可以进行调用的方法或属性。 当一个方法或属性被标记为 [__DynamicallyInvokable]&#xff0c;它表明这个成员在动态语言的环境中是可调用的。换句话说&#xff0c;…...

2024年最新10款顶级项目管理软件排行

项目管理软件在现代项目管理中扮演着至关重要的角色&#xff0c;它不仅仅是一个工具&#xff0c;更是一种高效、系统化的方法来管理和优化项目流程&#xff0c;帮助项目经理和团队成员快速了解项目状态&#xff0c;加速项目进展。 进度猫 进度猫是一款以甘特图为向导的轻量级…...

Python NLTK进阶:深入自然语言处理

目录 Python NLTK进阶&#xff1a;深入自然语言处理 1. 文本处理技术 1.1 命名实体识别&#xff08;NER&#xff09; 1.2 共指消解 2. 语义分析 2.1 语义角色标注&#xff08;SRL&#xff09; 2.2 词义消歧&#xff08;Word Sense Disambiguation&#xff09; 3. 机器学…...

【React 的理解】

谈一谈你对 React 的理解 对待这类概念题&#xff0c;讲究一个四字口诀“概用思优”&#xff0c;即“讲概念&#xff0c;说用途&#xff0c;理思路&#xff0c;优缺点&#xff0c;列一遍” 。 React 是一个网页 UI 框架&#xff0c;通过组件化的方式解决视图层开发复用的问题&a…...

软件压力测试有多重要?北京软件测试公司有哪些?

软件压力测试是一种基本的质量保证行为&#xff0c;它是每个重要软件测试工作的一部分。压力测试是给软件不断加压&#xff0c;强制其在极限的情况下运行&#xff0c;观察它可以运行到何种程度&#xff0c;从而发现性能缺陷。 在数字化时代&#xff0c;用户对软件性能的要求越…...

十四届蓝桥杯STEMA考试Python真题试卷第二套第五题

来源:十四届蓝桥杯STEMA考试Python真题试卷第二套编程第五题 本题属于迷宫类问题,适合用DFS算法解决,解析中给出了Python中 map() 和列表推导式的应用技巧。最后介绍了DFS算法的两种常见实现方式——递归实现、栈实现,应用场景——迷宫类问题、图的连通性、树的遍历、拓朴排…...

虚拟机 Ubuntu 扩容

文章目录 一、Vmware 重新分配 Ubuntu 空间二、Ubuntu 扩容分区 一、Vmware 重新分配 Ubuntu 空间 先打开 Vmware &#xff0c;选择要重新分配空间的虚拟机 点击 编辑虚拟机设置 &#xff0c;再点击 硬盘 &#xff0c;再点击 扩展 选择预计扩展的空间&#xff0c;然后点击 扩展…...

内网远程连接解决方案【Frp】

1、从https://github.com/fatedier/frp/releases下载需要的版本&#xff0c;如 frp_0.61.0_linux_amd64.tar.gz 2、解压tar -xvf frp_0.61.0_linux_amd64.tar.gz 3、配置服务端【外网云主机】&#xff0c;修改ftps.toml文件&#xff1a; bindPort 7000 vhostHTTPPort8000…...

浙江欧瑞雅装饰材料有限公司:空间的艺术,定制的智慧!

浙江欧瑞雅装饰材料有限公司&#xff1a;空间的艺术&#xff0c;定制的智慧&#xff01;在追求生活品质与空间利用并重的当下&#xff0c;浙江欧瑞雅装饰材料有限公司以其卓越的全屋定制服务&#xff0c;成为了众多家庭优化居住环境的理想选择。这家公司&#xff0c;凭借其深厚…...

jfrog artifactory oss社区版,不支持php composer私库

一、docker安装 安装环境&#xff1a;centos操作系统&#xff0c;root用户。 如果是mac或ubuntu等操作系统的话&#xff0c;会有许多安装的坑等着你。 一切都是徒劳&#xff0c;安装折腾那么久&#xff0c;最后还是不能使用。这就是写本文的初衷&#xff0c;切勿入坑就对了。 …...

华为OD机试真题-用户调度问题-2024年OD统一考试(E卷)

最新华为OD机试考点合集:华为OD机试2024年真题题库(E卷+D卷+C卷)_华为od机试题库-CSDN博客 每一题都含有详细的解题思路和代码注释,精编c++、JAVA、Python三种语言解法。帮助每一位考生轻松、高效刷题。订阅后永久可看,发现新题及时跟新。 题目描述 在通信系统中,一…...

前端与后端长连接 方法

1、SSE 一、SSE的主要特点 单向通信​&#xff1a;SSE是服务器向客户端的单向通信&#xff0c;客户端不能直接通过SSE向服务器发送消息。文本数据流​&#xff1a;SSE传输的主要是文本数据&#xff08;通常是JSON格式&#xff09;&#xff0c;不适合二进制数据。自动重连​&a…...

建议AI产品经理面试准备到这个程度再去

AI产品经理的面试整体的难度不高&#xff0c;和面试官探讨了很多关于做AI平台的方向和思考&#xff0c;其中AI智能客服的搭建被问到的次数最多&#xff01;面试官也解释了很多他们现在碰到的业务问题和解决方案&#xff0c;收获还是很多的~ ⏭️AI智能客服项目如下 1️⃣ 【预…...

智能交通的未来:深度学习如何改变车辆检测游戏规则

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

家具制造的效率与美观并重,玛哈特矫平机让家具产品更具竞争力。

在家具制造业中&#xff0c;效率与美观度的双重追求一直是企业关注的焦点。一方面&#xff0c;高效率的生产流程能够缩短交货周期&#xff0c;降低成本&#xff0c;提升企业的市场竞争力&#xff1b;另一方面&#xff0c;美观大方的家具设计则能吸引消费者的目光&#xff0c;提…...

交叉编译gcc

文章目录 前言下载gcc下载依赖项下载其他依赖项 configure选项--enable-languagesCXX和CXX_FOR_TARGETCFLAGS和CXXFLAGS--with-build-time-tools 使用小结 前言 前一阵用qemu做了个基于virt板卡的虚拟机&#xff0c;在不断完善&#xff0c;这两天想添加一个gcc进去&#xff0c…...

[VUE]框架网页开发1 本地开发环境安装

前言 其实你不要看我的文章比较长&#xff0c;但是他就是很长&#xff01;步骤其实很简单&#xff0c;主要是为新手加了很多解释&#xff01; 步骤一&#xff1a;下载并安装 Node.js 访问 Node.js 官网&#xff1a; Node.js — Download Node.js 下载 Windows 64 位版本&…...

终极QMC解密指南:如何快速将QQ音乐加密音频转换为MP3/FLAC格式

终极QMC解密指南&#xff1a;如何快速将QQ音乐加密音频转换为MP3/FLAC格式 【免费下载链接】qmc-decoder Fastest & best convert qmc 2 mp3 | flac tools 项目地址: https://gitcode.com/gh_mirrors/qm/qmc-decoder 你是否曾经从QQ音乐下载了喜欢的歌曲&#xff0c…...

CAXA 引出说明

位置同 CAD 里引线。效果示例设置样式默认样式&#xff0c;GB_引出说明&#xff08;1984&#xff09;Tip&#xff1a;如果引线样式需求是和标注样式一致&#xff0c;就使用“标注” 这一个样式就可以了。场景例如&#xff0c;标注比例是 1:4&#xff1b;但有个地方需要用文字引…...

MCU上的深度学习流量分类:HW-NAS优化与部署实践

1. 微控制器上的深度学习流量分类挑战在物联网设备爆炸式增长的时代&#xff0c;网络流量分类&#xff08;Traffic Classification&#xff09;已成为保障通信安全和优化网络性能的关键技术。传统基于端口号或深度包检测&#xff08;DPI&#xff09;的方法面对加密流量时束手无…...

[开源] 康复处方安全卫士:面向康复科与临床药学的处方前置风险拦截系统

本项目是专为康复医学场景设计的处方安全校验工具&#xff0c;对接医院信息系统&#xff08;HIS&#xff09;中的康复理疗处方流程&#xff0c;在医生提交前实时识别禁忌证与物理因子之间的互斥风险。核心机制由两部分构成&#xff1a;一是基于 YAML 定义的「禁忌证物理因子」互…...

Pikachu暴力破解实战:Burp Suite爆破思维训练全解析

1. 这不是“练手”&#xff0c;是真实世界暴力破解的完整沙盘推演很多人第一次点开Pikachu漏洞练习平台的“暴力破解”模块时&#xff0c;下意识觉得&#xff1a;“不就是写个脚本跑密码字典嘛&#xff1f;Python requests for循环&#xff0c;十分钟搞定。”我当年也是这么想…...

Burp Suite实操避坑指南:从抓包失败到漏洞验证的完整链路

1. 这不是又一本“Burp Suite入门指南”&#xff0c;而是一份我亲手调试过37次配置、在真实客户环境里跑通21个靶场、被5个刚转行的安全新人追着问细节的实操手记你点开这个标题&#xff0c;大概率正站在两个路口之间&#xff1a;一边是满屏英文弹窗、Proxy拦截失败、Repeater发…...

为什么你的ChatGPT演讲稿总被说“像机器人”?深度拆解人类共情节奏建模与提示词嵌入技术

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;为什么你的ChatGPT演讲稿总被说“像机器人”&#xff1f; 当你精心调用 ChatGPT 生成一篇 800 字的 TED 风格演讲稿&#xff0c;满怀期待地朗读给同事听&#xff0c;却收到一句扎心反馈&#xff1a;“很…...

基于神经网络的带输出三相逆变器模型预测控制LC滤波器附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长毕业设计辅导、数学建模、数据处理、程序设计科研仿真。&#x1f34e;完整代码获取 定制创新 论文复现点击&#xff1a;Matlab科研工作室&#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#x1f3…...

在Python项目中实现故障转移通过Taotoken自动切换备用大模型

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 在Python项目中实现故障转移通过Taotoken自动切换备用大模型 应用场景类&#xff0c;面向构建高可用AI应用的中高级开发者。当核心…...

Grafana告警规则配置实战

Grafana告警规则配置实战 一、Grafana告警概述 Grafana提供强大的告警功能&#xff0c;可以基于Prometheus等数据源触发告警通知。 1.1 告警流程 ┌────────────────────────────────────────────────────────────…...