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

websocket和SSE学习记录

websocket学习记录

websocket使用场景

  1. 即时聊天
  2. 在线文档协同编辑
  3. 实施地图位置

从开发角度来学习websocket开发

即使通信项目

  1. 通过node建立简单的后端接口,利用fs, path, express
app.get('*', (req, res) => {const assetsType = req.url.split('/')[1]if (assetsType == 'YouChat'){ // 首页const filepath = path.join(path.resolve('./dist'), 'index.html')res.sendFile(filepath)}if (assetsType == 'assets'){ // 客户端资源const filepath = path.join(path.resolve('./dist'), req.url)res.sendFile(filepath.split('?')[0]) // 去hash}if (assetsType == 'file'){ // 服务端资源const filepath = path.join(path.resolve('./'), req.url)res.sendFile(filepath)}if (assetsType == 'loadImg'){ // 接口res.send({ret: 1, data: {portrait, emoticon}})}
})

涉及到一个技术点Notification

核心的websocket建立连接的代码
用户注册,将用户的数据进行一个保存,然后初始化websocket的服务,将数据进行一个本地的localstorage的存储

    info.setData('name', userName)info.setData('url', sPorSrc)initWebSocket()localStorage.setItem('YouChatName', userName)localStorage.setItem('YouChatPor', sPorSrc)

初始化websocket的服务主要的代码为
2. 建立连接, window.socket.on,使用的是socket.io这个库,socket.io是基于事件驱动的实时通信库, 底层默认使用的是websocket的协议。会自动处理兼容问题,不支持websocket的情况下可以回退到轮询方案。发布订阅模式
剩下的就是逻辑的处理了
连接事件中注册登录时间,监听登录时间,写入数据,监听各种不同的事件,根据事件对数据进行处理。
如下为注册,监听的事件

import info from './info.js'
import view from './view.js'export default function(){window.socket = io()window.socket.on('connect', () => { // 连接成功const userInfo = {name: info.name,url: info.url,id: window.socket.id}info.setData('id', window.socket.id)window.socket.emit('login', userInfo)})// 登陆window.socket.on('login', userInfo => {view.drawUserList(userInfo)})// 获取当前在线列表window.socket.on('userList', userList => {view.drawUserList(userList)})// 退出window.socket.on('quit', id => {view.drawUserList(id)})// 接收群聊消息window.socket.on('sendMessageGroup', message => {info.groupMessageList.push(message)if (info.member == 'group'){view.drawMessageList(info.groupMessageList)}else{// 提示群聊新消息$('.top .group').setAttribute('data-new', 'true')let nNewNum = $('.top .group').getAttribute('data-message')$('.top .group').setAttribute('data-message', Number(nNewNum) + 1)new Notification('收到来自简言的新消息', {body: `${message.name}: ${message.text}`,icon: message.url})}})// 接收私聊消息window.socket.on('sendMessageMember', message => {if (message.id == info.id){ // 自己的消息回传if (info[`member__${message.memberId}`] == undefined) {info[`member__${message.memberId}`] = []}info[`member__${message.memberId}`].push(message)view.drawMessageList(info[`member__${message.memberId}`])}else{ // 好友私聊消息if (info[`member__${message.id}`] == undefined){info[`member__${message.id}`] = []}info[`member__${message.id}`].push(message)}if (info.member == message.id){view.drawMessageList(info[`member__${message.id}`])}else{// 提示私聊新消息if ($(`.item[data-id="${message.id}"]`)){$(`.item[data-id="${message.id}"]`).setAttribute('data-new', 'true')let nNewNum = $(`.item[data-id="${message.id}"] .item-name`).getAttribute('data-message')$(`.item[data-id="${message.id}"] .item-name`).setAttribute('data-message', Number(nNewNum)+1)new Notification('收到来自简言的新消息', {body: `${message.name}: ${message.text}`,icon: message.url})}}// userList 消息摘要if ($(`.item[data-id="${message.id}"]`)){$(`.item[data-id="${message.id}"] .item-text`).innerHTML = message.text || `[收到新灵魂]`}})
}

其中的各种事件,就是前端逻辑的处理了。这是一个简单的websocket的demo。
学习的是https://github.com/cp0725/YouChat这个库,建议加一个脚本,build: “webpack --config webpack.config.js”, 方便开发调试

心跳检测

WebSocket 心跳检测的本质
本质是通过周期性双向验证维持长连接的活性,解决以下核心问题:

网络中间层的「假性存活」

现象:虽然 TCP 层连接未断开,但防火墙/Nginx 等中间件会主动关闭长时间(如 5 分钟)无数据传输的连接

解法:通过定时发送轻量级探测包(心跳包)重置中间件的空闲计时器

「半开连接」黑洞问题

现象:客户端异常断网后,服务端无法感知连接已失效,持续等待消息

解法:通过双向心跳响应机制,实现连接状态实时探活

与 WebSocket 协议特性的深度结合

协议头优化

心跳包利用 WebSocket 的极简帧头(最低 2 字节),相比 HTTP 头节省 90%+ 流量

扩展协议支持

通过 Sec-WebSocket-Extensions 协商心跳参数(如间隔时间)

可自定义心跳包格式(如携带设备电量、网络类型等元数据)

无跨域特性

心跳机制可跨域运行,无需像 HTTP 轮询那样处理 CORS 问题

http 通过判断 header 中是否包含 Connection: Upgrade 与 Upgrade: websocket 来判断当前是否需要升级到 websocket 协议,除此之外,还有其它 header:

Sec-WebSocket-Key :浏览器随机生成的安全密钥
Sec-WebSocket-Version :WebSocket 协议版本
Sec-WebSocket-Extensions :用于协商本次连接要使用的 WebSocket 扩展
Sec-WebSocket-Protocol :协议
当服务器同意进行 WebSocket 连接时,返回响应码 101

WebSocket 特点:

支持双向通信,实时性更强;
可以发送文本,也可以二进制文件;
协议标识符是 ws,加密后是 wss ;
较少的控制开销。连接创建后,ws客户端、服务端进行数据交换时,协议控制的数据包头部较小。在不包含头部的情况下,服务端到客户端的包头只有 2~10 字节(取决于数据包长度),客户端到服务端的的话需要加上额外的 4 字节的掩码。而 HTTP 协议每次通信都需要携带完整的头部;
支持扩展。ws 协议定义了扩展,用户可以扩展协议,或者实现自定义的子协议。(比如支持自定义压缩算法等)
无跨域问题。

SSE

sse是服务器向客户端推送, 用的是https的长连接,支持自动重连

const express = require('express');
const app = express();
const port = 3000;// 允许跨域(开发环境用)
app.use((req, res, next) => {res.header('Access-Control-Allow-Origin', '*');next();
});// SSE 路由
app.get('/sse-stream', (req, res) => {// 设置 SSE 必需的头信息res.writeHead(200, {'Content-Type': 'text/event-stream','Cache-Control': 'no-cache','Connection': 'keep-alive'});// 发送初始数据res.write('event: connected\ndata: Welcome!\n\n');// 定时发送数据(模拟实时更新)let counter = 0;const timer = setInterval(() => {counter++;const data = {time: new Date().toISOString(),value: counter};// SSE 标准格式(注意换行符)res.write(`event: update\n`);res.write(`data: ${JSON.stringify(data)}\n\n`);}, 1000);// 客户端断开时清理req.on('close', () => {clearInterval(timer);res.end();});
});app.listen(port, () => {console.log(`Server running at http://localhost:${port}`);
});
<!DOCTYPE html>
<html>
<body><div id="sse-data"></div><script>const eventSource = new EventSource('http://localhost:3000/sse-stream');// 通用消息处理(默认事件)eventSource.onmessage = (e) => {console.log('Default event:', e.data);};// 自定义事件处理(对应服务端的 event:update)eventSource.addEventListener('update', (e) => {const data = JSON.parse(e.data);document.getElementById('sse-data').innerHTML = `Time: ${data.time}<br>Counter: ${data.value}`;});// 连接建立事件eventSource.addEventListener('connected', (e) => {console.log('Connection established:', e.data);});// 错误处理eventSource.onerror = (e) => {if (e.eventPhase === EventSource.CLOSED) {console.log('Connection closed');} else {console.error('SSE Error:', e);}// 自动重连(浏览器默认行为)};// 页面关闭时断开连接window.addEventListener('beforeunload', () => {eventSource.close();});</script>
</body>
</html>

相关文章:

websocket和SSE学习记录

websocket学习记录 websocket使用场景 即时聊天在线文档协同编辑实施地图位置 从开发角度来学习websocket开发 即使通信项目 通过node建立简单的后端接口,利用fs&#xff0c; path&#xff0c; express app.get(*, (req, res) > {const assetsType req.url.split(/)[…...

【统计分析120】统计分析120题分享

1-30 判断题 数学模型 指的是通过抽象、简化现实世界的某些现象&#xff0c;利用数学语言来描述他们的结构和行为&#xff0c;做出一些必要的假设&#xff0c;运用适当的数学工具&#xff0c;得到一个数学结论 数学模型&#xff1a;指的是通过抽象、简化现实世界的某些现象&am…...

【计量地理学】实验四 主成分分析与莫兰指数

一、实验内容 &#xff08;一&#xff09; 某地区35个城市2004年的7项经济统计指标数据见&#xff08;数据中的“题目1”sheet&#xff09;。 &#xff08;1&#xff09;试用最短距离聚类法对35个城市综合实力进行系统聚类分析&#xff0c;并画出聚类谱系图: 在此次实验内容…...

手写call,bind,apply

foo.Mycall(obj,1,2,3) Function.prototype.Mycallfunction(target,...args){if(typeof this!function){throw new TypeError(this is not a function)}// 判断target是否是对象if(targetnull||targetundefined){targetwindow}if(typeof target!object){targetObject(target)}/…...

【读书笔记·VLSI电路设计方法解密】问题64:什么是芯片的功耗分析

低功耗设计是一种针对VLSI芯片功耗持续攀升问题的设计策略。随着工艺尺寸微缩&#xff0c;单颗芯片可集成更多元件&#xff0c;导致功耗相应增长。更严峻的是&#xff0c;现代芯片工作频率较二十年前大幅提升&#xff0c;而功耗与频率呈正比关系。因此&#xff0c;芯片功耗突破…...

Ubuntu18.04安装Qt5.12

本文介绍了在Ubuntu18.04环境下安装QT QT5.12相关安装包下载地址 https://download.qt.io/archive/qt/5.12/ Linux系统下Qt的离线安装包以.run结尾 (sudo apt-get install open-vm-tools open-vm-tools-desktop解决无法paste的问题) 安装 1.cd命令 终端进入对应的文件夹下面 2.…...

【SpringBoot】99、SpringBoot中整合RabbitMQ实现重试功能

最近在做一个项目,需要使用 MQ 实现重试功能,在这里给各位分享一下。 1、整合 RabbitMQ <!-- rabbitmq消息队列 --> <dependency><groupId>org.springframework.boot</groupId><...

max31865典型电路

PT100读取有很多种方案&#xff0c;常用的惠斯通电桥&#xff0c;和专用IC max31865 。 电阻温度检测器(RTD)是一种阻值随温度变化的电阻。铂是最常见、精度最高的测温金属丝材料。铂RTD称为PT-RTD&#xff0c;镍、铜和其它金属亦可用来制造RTD。RTD具有较宽的测温范围&#x…...

每日一道leetcode(补充版)

1004. 最大连续1的个数 III - 力扣&#xff08;LeetCode&#xff09; 题目 给定一个二进制数组 nums 和一个整数 k&#xff0c;假设最多可以翻转 k 个 0 &#xff0c;则返回执行操作后 数组中连续 1 的最大个数 。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1,0,0,0,1…...

数据通信学习笔记之OSPF的区域

OSPFArea 用于标识一个 OSPF 的区域 区域是从逻辑上将设备划分为不同的组&#xff0c;每个组用区域号 (Area ID)来标识 OSPF 的区域 ID 是一个 32bit 的非负整数&#xff0c;按点分十进制的形式(与 IPV4 地址的格式一样)呈现&#xff0c;例如 Area0.0.0.1。 为了简便起见&#…...

5 提示词工程指南-计划与行动

5 提示词工程指南-计划与行动 计划与行动 Cline 有两种模式: Plan 描述目标和需求、提问与回答、讨论、抽象项目的各个方面、确定技术路线、确定计划 计划与确认相当于架构师,不编写代码Act 按计划编写代码 按照计划编码Plan 模式的本质是构建实际编码前的上下文,Act 的本…...

如何一键批量删除多个 Word 文档中的页眉和页脚

在工作中&#xff0c;许多 Word 文档的页眉页脚中包含公司名称、Logo、电话等信息&#xff0c;用于对外宣传。但有时我们需要批量删除这些页眉页脚信息&#xff0c;尤其当信息有误时&#xff0c;手动逐个删除会增加工作量&#xff0c;导致效率低下。本文将介绍一种便捷的方法&a…...

QCustomPlot中自定义图层

QCustomPlot 使用图层(QCPLayer)系统来组织绘图元素的绘制顺序和可见性。下面详细介绍如何自定义图层并将可绘制对象关联到特定图层。 1. 理解 QCustomPlot 的图层系统 QCustomPlot 的图层系统具有以下特点&#xff1a; 图层按顺序排列&#xff0c;后绘制的图层会覆盖前面的图…...

Dubbo QoS操作手册

QOS 操作手册 QoS概述 启动参数 参数说明默认值qos-enable是否启动Qostrueqos-port启动Qos绑定的端口22222qos-accept-foreign-ip是否运行远程访问falseqos-accept-foreign-whitelist支持的远端地址ip地址&#xff08;段&#xff09;无qos-anonymous-access-permission-lefe…...

-实用类-

1. API是什么 2.什么是枚举 &#xff01;有点类似封装&#xff01; 2.包装类 注意&#xff1a; 1.Boolean类构造方法参数为String类型时&#xff0c;若该字符串内容为true(不考虑大小写)&#xff0c;则该Boolean对象表示true&#xff0c;否则表示false 2.当包装类构造方法参…...

Apache Parquet 文件组织结构

简要概述 Apache Parquet 是一个开源、列式存储文件格式&#xff0c;最初由 Twitter 与 Cloudera 联合开发&#xff0c;旨在提供高效的压缩与编码方案以支持大规模复杂数据的快速分析与处理。Parquet 文件采用分离式元数据设计 —— 在数据写入完成后&#xff0c;再追加文件级…...

Spring 事务管理核心机制与传播行为应用

Spring 事务详解 一、Spring 事务简介 Spring 事务管理基于 AOP&#xff08;面向切面编程&#xff09;实现&#xff0c;通过 声明式事务&#xff08;注解或 XML 配置&#xff09;统一管理数据库操作&#xff0c;确保数据一致性。核心目标&#xff1a;保证多个数据库操作的原子…...

从零开始解剖Spring Boot启动流程:一个Java小白的奇幻冒险之旅

大家好呀&#xff01;今天我们要一起探索一个神奇的话题——Spring Boot的启动流程。我知道很多小伙伴一听到"启动流程"四个字就开始头疼&#xff0c;别担心&#xff01;我会用最通俗易懂的方式&#xff0c;带你从main()方法开始&#xff0c;一步步揭开Spring Boot的…...

集合框架(重点)

1. 什么是集合框架 List有序插入对象&#xff0c;对象可重复 Set无序插入对象&#xff0c;对象不可重复&#xff08;重复对象插入只会算一个&#xff09; Map无序插入键值对象&#xff0c;键只唯一&#xff0c;值可多样 &#xff08;这里的有序无序指的是下标&#xff0c;可…...

IPv4地址分类与常用网络地址详解

常见的 IPv4 地址分类&#xff1a; 1. A 类地址&#xff08;Class A&#xff09; 范围&#xff1a;0.0.0.0 到 127.255.255.255 默认子网掩码&#xff1a;255.0.0.0 或 /8 用途&#xff1a;通常用于大型网络&#xff0c;例如大型公司、组织。 特点&#xff1a; 网络地址范围…...

模拟实现memmove,memcpy,memset

目录 前言 一、模拟实现memmove 代码演示&#xff1a; 二、模拟实现memcpy 代码演示&#xff1a; 三、模拟实现memset 代码演示&#xff1a; 总结 前言 这篇文章主要讲解了库函数的模拟实现&#xff0c;包含memmove&#xff0c;memcpy&#xff0c;memset 一、模拟实现m…...

uni-app 开发安卓 您的应用在运行时,向用户索取(定位、相机、存储)等权限,未同步告知权限申请的使用目的,不符合相关法律法规要求

您的应用在运行时,向用户索取(定位、相机、存储)等权限,未同步告知权限申请的使用目的,不符合相关法律法规要求。 测试步骤:1、 工作台 -打卡,申请定位权限;2、工作台-设置-编辑资料-更换头像,申请相机、存 储权限。 修改建议:APP在申请敏感权限时,应同步说明权限申…...

RHCSA Linux 系统文件内容显示2

6. 过滤文件内容显示 grep &#xff08;1&#xff09;功能&#xff1a;在指定普通文件中查找并显示含指定字符串的行&#xff0c;也可与管道符连用。 &#xff08;2&#xff09;格式&#xff1a;grep 选项... 关键字字符串 文件名... &#xff08;3&#xff09;常用选项及说…...

C语言状态字与库函数详解:概念辨析与应用实践

C语言状态字与库函数详解&#xff1a;概念辨析与应用实践 一、状态字与库函数的核心概念区分 在C语言系统编程中&#xff0c;"状态字"和"库函数"是两个经常被混淆但本质完全不同的概念&#xff0c;理解它们的区别是掌握系统编程的基础。 1. 状态字&…...

【2】Kubernetes 架构总览

Kubernetes 架构总览 主节点与工作节点 主节点 Kubernetes 的主节点&#xff08;Master&#xff09;是组成集群控制平面的关键部分&#xff0c;负责整个集群的调度、状态管理和决策。控制平面由多个核心组件构成&#xff0c;包括&#xff1a; kube-apiserver&#xff1a;集…...

Redis下载

目录 安装包 1、使用.msi方式安装 2.使用zip方式安装【推荐方式】 添加环境变量 配置后台运行 启动&#xff1a; 1.startup.cmd的文件 2.cmd窗口运行 3.linux源码安装 &#xff08;1&#xff09;准备安装环境 &#xff08;2&#xff09;上传安装文件 &#xff08;3&…...

React 文章 分页

删除功能 携带路由参数跳转到新的路由项 const navigate useNavigate() 根据文章ID条件渲染...

OpenCV 图形API(39)图像滤波----同时计算图像在 X 和 Y 方向上的一阶导数函数SobelXY()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::gapi::SobelXY 函数是 OpenCV 的 G-API 模块中用于同时计算图像在 X 和 Y 方向上的一阶导数&#xff08;即 Sobel 边缘检测&#xff09;的一…...

传导发射测试(CE)和传导骚扰抗扰度测试(CS)

传导发射测试(CE)&#xff1a; 测量接收机&#xff1a; 是EMI测试中最常用的基本测试仪器&#xff0c;仪器类型包括准峰值测量接收机、峰值测量接收机、平均值测量接收机和均方根值测量接收机。测量接收机的几个重要指标分别是&#xff1a;6dB处的带宽、充电时间常数、放电时…...

ubuntu 查看现在服务使用的端口

1. 使用netstat命令 netstat是一个常用的网络工具&#xff0c;可以显示网络连接、路由表、接口统计等信息。虽然在较新的系统中netstat可能被ss命令替代&#xff0c;但仍然可以通过安装net-tools包来使用它。 安装net-tools&#xff1a; sudo apt-get install net-tools 查看…...