网络-WebSocket


文章目录

  • 前言
  • 一、WebSocket简介
    • 应用场景
    • 原理
  • 二、使用
    • 心跳监测
    • 广播消息
  • 三、群聊demo
  • 总结


前言

本文主要记录WebSocket的简单介绍和使用,完成群聊的demo


一、WebSocket简介

WebSocket是一种通信协议,它通过单个TCP连接提供全双工的通信通道。
它允许客户端和服务器之间进行实时的双向通信。
与传统的HTTP请求不同,WebSocket建立了客户端和服务器之间的持久连接,从而实现了高效和低延迟的通信。

要建立WebSocket连接,客户端向服务器发送WebSocket握手请求,服务器则以WebSocket握手响应进行回应。
一旦连接建立,客户端和服务器都可以异步地发送消息。

WebSocket采用基于消息的通信模型,消息以帧的形式通过WebSocket连接发送。
这些帧可以是二进制或文本形式,具体取决于应用程序的需求。
该协议还支持消息分片、用于保持连接的ping/pong消息以及用于优雅终止连接的关闭消息等功能。
WebSocket得到了大多数现代Web浏览器的支持,并且可以在服务器端应用程序中使用提供WebSocket功能的库或框架

应用场景

  • 实时性要求高,如:聊天、游戏、数据可视化
  • 需要频繁交换数据,如:实时协作工具、文件管理器
  • 需要推送服务的应用,如:实时数据监控、通知系统
  • 跨平台应用,如:桌面应用、移动端应用

它提供了比长轮询或服务器推送事件(SSE)更高效的替代方案。

原理

  • 握手阶段:客户端发送一个HTTP请求给服务器,请求升级为WebSocket协议。在请求头中包含一些特殊的字段,如UpgradeConnection,表明客户端希望升级到WebSocket协议,这里也可以使用这里也可以使用WebSocket API进行通讯API进行通讯,实际也是发送GET请求带特殊请求头。服务器收到请求后,如果支持WebSocket协议,则返回一个HTTP响应,状态码为101 Switching Protocols,表示升级成功。

101

  • 建立连接:一旦握手成功,客户端和服务器之间建立了一个持久的双向连接。这个连接是基于TCP的,可以实现全双工通信,即客户端和服务器可以同时发送和接收消息。
    数据传输:客户端和服务器可以通过WebSocket连接发送和接收消息。消息以帧的形式进行传输,可以是二进制数据或文本数据。帧包含了一些控制信息,如消息类型、消息长度等。客户端和服务器可以异步地发送和接收消息,实现实时的双向通信。
  • 保持连接:WebSocket连接是持久的,不会像传统的HTTP请求那样每次都需要重新建立连接。为了保持连接的活跃状态,客户端和服务器可以定期发送心跳消息,以确保连接不会断开。
  • 关闭连接:当客户端或服务器希望关闭WebSocket连接时,可以发送一个关闭帧。接收到关闭帧的一方会响应一个关闭帧,然后双方的连接会被正常关闭。

二、使用

  • 创建ws对象
const ws = new WebSocket('ws://localhost:8080');
  • 监听连接成功
ws.onopen = function () {console.log('已连接')}
  • 发送消息
ws.send('发送的消息')
  • 接收消息
 ws.onmessage = function (e) {console.log(e.message)}
  • 断开连接
ws.close()
  • 监听断开连接
ws.onclose = function() {console.log('WebSocket连接已关闭');};
  • 监听连接错误
ws.onerror = function(error) {console.error('WebSocket连接发生错误:', error);};
  • 事件监听器
    WS是可以添加事件监听器的,如open、message、close、error等与属性效果是一致的。
 ws.addEventListener('open',function (event) {console.log('连接成功')isConnected = true;})
ws.addEventListener('message',(e)=>{let li = document.createElement('li')let data = JSON.parse(e.data)if (data.type == 2){li.innerText = data.messagelist.appendChild(li)}else {console.log(data.message)}})

心跳监测

socket连接在长时间不使用、网络波动、弱网状况下有可能断开连接,需要进行心跳监测来保证连接存活。在断开连接时,实现重连,在进行心跳消息发送时,客户端需要将心跳监测信息过滤掉。

 let heartInreaval = nullconst heartCheck = () =>{// 等于open 发送心跳if (socket.readyState === ws.OPEN){socket.send(JSON.stringify({type:state.HEART,message:'心跳检测'}))}else {clearInterval(heartInreaval)}}setInterval(heartCheck,5000)

广播消息

在后端直接使用send发送消息只能针对点对点的,不能将消息发送给全部连接,需要使用clients属性遍历发送,达到广播的效果

 // 广播消息wss.clients.forEach((client)=>{client.send(JSON.stringify({type:state.MESSAGE,message:e.toString()}))})

三、群聊demo

前端:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<div><ul id="list"></ul><input type="text" id="input"><button id="send">发送</button><button id="stop">断开连接</button>
</div>
</body>
<script>// 连接状态let isConnected = false;let input = document.getElementById('input')let btn = document.getElementById('send')let list = document.getElementById('list')let stop = document.getElementById('stop')function connectWebSocket() {// 创建ws实例const ws = new WebSocket('ws://localhost:8080');// 监听连接成功ws.addEventListener('open',function (event) {console.log('连接成功')isConnected = true;})btn.addEventListener('click',function () {if (input.value){// send发送消息ws.send(input.value)input.value = ''}})ws.addEventListener('message',(e)=>{let li = document.createElement('li')let data = JSON.parse(e.data)if (data.type == 2){li.innerText = data.messagelist.appendChild(li)}else {console.log(data.message)}})//断开连接stop.addEventListener('click',()=>{ws.close()})// ws.onopen = function () {//     console.log('已连接')// ws.send('发送的消息')// ws.onmessage = function (e) {//     console.log(e.message)// }// }ws.onclose = function() {console.log('WebSocket连接已关闭');isConnected = false;// 进行重连reconnect();};// 监听WebSocket连接发生错误事件ws.onerror = function(error) {console.error('WebSocket连接发生错误:', error);isConnected = false;// 进行重连reconnect();};}// 重连函数function reconnect() {if (!isConnected) {console.log('尝试重新连接...');setTimeout(connectWebSocket, 5000);}}connectWebSocket()</script>
</html>

后端:这里使用Node

//安装 ws
const ws =require('ws')
// 创建socket服务
const wss = new ws.Server({port:8080},()=>{console.log('socket服务启动成功')
})//心跳枚举
const state = {HEART:1,MESSAGE:2
}// 监听客户端连接
wss.on('connection',(socket)=>{//监听客户端消息console.log('客户端连接成功')socket.on('message',(e)=>{console.log(e.toString())// 广播消息wss.clients.forEach((client)=>{client.send(JSON.stringify({type:state.MESSAGE,message:e.toString()}))})})let heartInreaval = nullconst heartCheck = () =>{// 等于open 发送心跳if (socket.readyState === ws.OPEN){socket.send(JSON.stringify({type:state.HEART,message:'心跳检测'}))}else {clearInterval(heartInreaval)}}setInterval(heartCheck,5000)
})

群聊


总结

WebSocket通过握手阶段建立持久的双向连接,然后通过帧的方式传输数据,实现实时的双向通信。它相比传统的HTTP请求具有更低的延迟和更高的效率,适用于需要实时更新的Web应用程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/131685.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ARM:使用汇编完成三个灯流水亮灭

1.汇编源代码 .text .global _start _start: 设置GPIOF寄存器的时钟使能LDR R0,0X50000A28LDR R1,[R0]ORR R1,R1,#(0x1<<5)STR R1,[R0]设置GPIOE寄存器的时钟使能LDR R0,0X50000A28LDR R1,[R0] 从r0为起始地址的4字节数据取出放在R1ORR R1,R1,#(0x1<<4) 第4位设…

18基于matlab的二阶动态系统的滑膜控制,程序已调通,可直接运行。标价为程序价格,不包含售后。程序保证可直接运行。

基于matlab的二阶动态系统的滑膜控制&#xff0c;程序已调通&#xff0c;可直接运行。标价为程序价格&#xff0c;不包含售后。程序保证可直接运行。 18matlab滑膜控制 (xiaohongshu.com)

学习记忆——数学篇——案例——代数——方程——一元二次方程

重点记忆法 a x 2 b x c 0 ax^2bxc0 ax2bxc0 整体可以由&#xff1a; 根&#xff08;多少&#xff0c;正负&#xff0c;区间&#xff09; ⟹ \Longrightarrow ⟹ △ △ △ ⟹ \Longrightarrow ⟹ 求根公式 x 1 , 2 x_{1,2} x1,2​ − b △ 2 a \frac{-b\sqrt{△}}{2a} 2…

【Unity】【VR】如何让Distance Grab抓取物品时限制物品的Rotation

【背景】 遇到这样的场景,希望抓取Canvas时,Canvas不会沿Z轴旋转。 【问题】 发现Freeze Canvas的Rigid Body没有用。 【分析】 应该是RigidBody的限制仅在物理互动下生效,抓取可能不属于物理互动(比如碰撞),所以不生效。 【思路】 还是得写脚本挂载在Interacta…

Hadoop分布式集群搭建教程

目录 前言环境准备一、创建虚拟机二、虚拟机网络配置三、克隆虚拟机四、Linux系统配置五、Hadoop的部署配置六、Hadoop集群的启动 前言 大数据课程需要搭建Hadoop分布式集群&#xff0c;在这里记录一下搭建过程 环境准备 搭建Haoop分布式集群所需环境&#xff1a; VMware&a…

lv8 嵌入式开发-网络编程开发 16 多路复用poll函数

目录 1 多路复用的多种实现方式 2 poll 2.1 poll 函数应用 3 epoll 函数族&#xff08;效率最高&#xff09; 3.1 epoll_create 创建epoll句柄 3.2 epoll_ctl epoll句柄控制接口 3.3 epoll_wait 等待 epoll 文件描述符上的 I/O 事件 3.4 epoll 函数应用 1 多路复用的多…

sqoop 脚本密码管理

1&#xff1a;背景 生产上很多sqoop脚本的密码都是铭文&#xff0c;很不安全&#xff0c;找了一些帖子&#xff0c;自己尝试了下&#xff0c;记录下细节&#xff0c;使用的方式是将密码存在hdfs上然后在脚本里用别名来替代。 2&#xff1a;正文 第一步&#xff1a;创建密码对…

【数据结构-队列 二】【单调队列】滑动窗口最大值

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【单调队列】&#xff0c;使用【队列】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&…

【大数据】hadoop安装部署(学习笔记)

一、集群组成概述 Hadoop集群包括两个集群&#xff1a;HDFS集群、YARN集群 两个集群逻辑上分离、通常物理上在一起 两个集群都是标准的主从架构集群 HDFS集群&#xff08;分布式存储&#xff09;&#xff1a; 主角色&#xff1a;NameNode从角色&#xff1a;DataNode主角色…

【JQuery插件】手把手教你如何白瓢一个网站的全部付费资源!前端狂喜

视频讲解地址&#xff1a;https://www.bilibili.com/video/BV1bm4y157GF/ 网站地址&#xff1a;https://www.jq22.com/ 大家好&#xff0c;这一集给大家分享一个好用的JQuery插件网站&#xff0c;当然&#xff0c;更主要的是教大家如何白瓢这个网站上的资源&#xff0c;这个网…

深度学习自学笔记十三:unet网络详解和环境配置

一、unet网络详解 UNet&#xff08;全名为 U-Net&#xff09;是一种深度学习架构&#xff0c;最初由Olaf Ronneberger、Philipp Fischer和Thomas Brox于2015年提出&#xff0c;用于图像分割任务。该网络的名称来源于其U形状的架构&#xff0c;该架构使得网络在编码和解码过程中…

Filebeat、metricbeat、kafka

kibana机子上安装filebeat&#xff08;因为有nginx&#xff09; 上传filebrat包 在es概览查看 上传metricbeat 排错 tailf !$ Kibana-Vlsualize查看 kafka(卡夫卡) kafka是一个分布式的消息发布—订阅系统&#xff08;kafka其实是消息队列&#xff09;消息队列中间件 Kafka的…