初识 WebSocket 协议

news/2025/3/20 10:56:05/文章来源:https://www.cnblogs.com/laozhenHome/p/18782312

什么是 WebSocket

WebSocket 是一种网络通信协议,是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通信的协议。WebSocket 属于应用层协议,它基于 TCP 传输协议,并复用 HTTP 的握手通道。

为什么出现 WebSocket

我们已经拥有了 HTTP 协议,为什么还要搞出一套 WebSocket 协议呢?
因为 HTTP 协议有一个缺陷:通信只能由客户端发起,服务端被动响应。要想实现实时通信,必须要客户端实现轮询或者长轮询机制,每次请求都需要完整 HTTP 头部,通信开销较大;每次 TCP 连接重建可能引入延迟问题。
有些场景比如实时聊天、在线协作、实时监控大屏等高频双向通信的场景不再适合使用 HTTP 请求,这时候 WebSocket 协议就应运而生了。

WebSocket 的优点

WebSocket 基于全双工通信,建立连接后客户端和服务器可以双向实时通信,它的特点如下:

  • 持久连接:一次握手后保持长连接,避免反复建立连接的开销。
  • 主动推送:建立连接后,服务器可以主动向客户端发送数据,无需等待请求。
  • 低开销:数据帧轻量(仅需 2~10 字节头部,而 HTTP 请求头通常数百字节)。
  • 低延迟:连接建立后,数据可以直接传输(无需 HTTP 头部冗余信息)。

如何实现 WebSocket 通信

WebSocket 复用了 HTTP 的握手通道,客户端通过 HTTP 请求与 WebSocket 服务端协商升级协议。协议升级完成后,后续的数据交换则遵照 WebSocket 的协议。

1. 客户端:申请协议升级

客户端发起协议升级请求,采用的是标准的 HTTP 报文格式,且只支持 GET 方法。

// 部分请求头
GET ws://localhost:8080/ HTTP/1.1
connection:Upgrade
host:localhost:8080
origin:http://192.168.10.6:8000
pragma:no-cache
sec-websocket-extensions:permessage-deflate; client_max_window_bits
sec-websocket-key:oBBcvePJE1NgPiGrza6JnQ==
sec-websocket-version:13
upgrade:websocket

在 URL ws://localhost:8080/ 中,ws 是 WebSocket 协议的标识符,它表示非加密的 WebSocket 协议,直接通过明文传输数据,类似于 HTTP 中的 http。WebSocket 协议的标识符还有 wss,它表示加密的 WebSocket 协议,基于 TLS/SSL 加密传输,用于保护敏感数据,类似于 HTTP 中的 https。

升级协议请求需要重点关注下面几个请求头字段:

  • Connection: Upgrade:表示连接要升级协议
  • Upgrade: websocket:表示要升级到 websocket 协议。
  • Sec-WebSocket-Version: 13:表示 websocket 的版本。如果服务端不支持该版本,需要返回一个 Sec-WebSocket-Versionheader,里面包含服务端支持的版本号。
  • Sec-WebSocket-Key:oBBcvePJE1NgPiGrza6JnQ==:与后面服务端响应首部的 Sec-WebSocket-Accept 是配套的,提供基本的防护,比如恶意的连接,或者无意的连接。

2. 服务端:响应协议升级

服务端返回内容如下,状态代码 101 表示协议切换。到此完成协议升级,后续的数据交互都按照新的协议来。

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: py6RSjDCGHR78M/JEOSfd3DrLQk=

响应头部字段 Sec-WebSocket-Accept 是根据客户端请求首部的 Sec-WebSocket-Key 计算出来的。服务端根据请求头字段 Sec-WebSocket-Key 的值跟字符串 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 拼接,然后对拼接后的值进行 SHA-1 哈希运算,最后将得到的哈希值进行 base64 编码最终得到 Sec-WebSocket-Accept 的值。

const crypto = require('crypto')
const magic = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
const secWebSocketKey = 'oBBcvePJE1NgPiGrza6JnQ=='let secWebSocketAccept = crypto.createHash('sha1').update(secWebSocketKey + magic).digest('base64')console.log(secWebSocketAccept) // py6RSjDCGHR78M/JEOSfd3DrLQk=

WebSocket 客户端、服务端通信的最小单位是帧(frame),由1个或多个帧组成一条完整的消息(message)。客户端将消息切割成多个帧,并发送给服务端;服务端接收消息帧,并将关联的帧重新组装成完整的消息。数据帧格式不再讲解,感兴趣的同学请参考 RFC6455 5.2节。

WebSocket 简单示例

以下是一个简单的 WebSocket 编程示例,客户端通过 WebSocket 向服务器(node实现)发送数据,并接收服务器返回的数据。
客户端部分代码如下:

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>WebSocket 示例</title>
</head>
<body><textarea></textarea><button onclick="sendConnection()">建立websocket连接</button><button onclick="sendMsgToServer()">发送信息</button><script>// 建立websocket连接function sendConnection() {ws = new WebSocket('ws://localhost:8080')ws.onopen = function () {console.log('ws onopen')clientLog('websocket连接成功')}ws.onmessage = function (e) {console.log('ws onmessage')console.log('来自服务端:', e.data)}ws.onerror = function (e) {console.log('ws onerror: s%', e)isOpenInterval = '0'clientLog('websocket连接出错')}ws.onclose = function (e) {console.log('ws onclose')isOpenInterval = '0'clientLog('关闭websocket连接')}}function sendMsgToServer() {if (!ws || ws.readyState !== 1) {clientLog('请先建立websocket连接')return}const textarea = document.querySelector('textarea')if (!textarea.value) {clientLog('请输入发送内容')return}ws.send(textarea.value)}</script>
</body>
</html>

服务端部分代码如下:

// 这里服务端用了ws这个库。
// 引入依赖
const app = require('express')()
const Websocket = require('ws')const wss = new Websocket.Server({port: 8080, // websocket监听端口
})// 监听websocket连接
wss.on('connection', ws => {console.log('服务端接受连接')ws.send('服务端:websocket连接已建立')// 监听客户端连接ws.on('message', message => {// 监听客户端消息console.log('服务端接受数据: %s', message)ws.send(`服务端:client端数据${message}已接收`)})// 监听客户端断开连接ws.on('close', () => {timer && clearInterval(timer)timer = nullconsole.log('服务端断开连接')ws.send('服务端:websocket连接已断开')ws.terminate()})
})// 监听端口
app.listen(3000, () => {console.log('服务端口:3000')
})

演示代码已放入 gitHub,请下载演示。

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

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

相关文章

易基因:WGBS+ChIP-seq技术揭示Cdx2转录因子在发育与稳态中的动态结合机制|NC/IF14.7

大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。 Cdx2是一个关键的转录因子,在小鼠肠道上皮细胞的发育过程中起着决定性的作用。它在胚胎期和成年期的肠道上皮细胞中都有表达,但其结合的基因组位点在发育和成年期有所不同。DNA甲基化是一种表观遗传修饰,通…

FALL

FALL 信息收集 扫描目标主机ip ┌──(root㉿kali)-[~] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:84:b2:cc, IPv4: 192.168.158.143 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.158.1 00:50:56:c0:0…

信创龙头股在政策支持下的投资机会解读

信创产业,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。近年来,随着政策的大力支持,信创产业发展势头迅猛,信创龙头股也备受投资者关注。在政策东风的助力下,信创龙头股蕴含着丰富的投资机会,值得深入剖析。 政策支…

通过 INFINI Console 集中管理极限网关配置

之前有做过介绍实现极限网关(INFINI Gateway) 配置动态加载,这是一个 Gateway 实例的操作,直接在服务器上修改配置文件。如果有多个 Gateway 实例需要调整,登录多台主机修改配置文件就有些繁琐,有没有简便的方法呢? 答案是: 当然有! INFINI Gateway 有配套的管理页面,…

如何精准控制生产成本?8年生产主管告诉我掌握这些底层逻辑!

你是不是常常听到“控制成本”这个词,但却搞不清楚到底应该从哪里入手? 其实,成本控制并不是简单的削减支出,而是要在每个环节上做到精益求精。 作为一名有8年经验的生产主管,我可以告诉你,成本控制的关键在于对生产过程中的每一环节都要有清晰的了解和精准的把控。下文介…

CIMCO Edit 2024软件下载与安装教程

CIMCO Edit 2024是Cimco Integration公司推出的一款强大的数控程序编辑器,可帮助用户进行存储和检索NC程序、NC程序优化、后处理、以及快速NC程序仿真,它拥有强大而实用的数控编辑功能、文件的智能比较、刀位轨迹的三维模拟、DNC传输等强大功能,可帮助用户更快捷的完成NC程序…

FunASR: 让AI听懂你的声音

分享一个语音识别黑科技——开源免费的FunASR!我们先看下Funasr的语音识别效果。第一个是识别MP4视频文件。第二个是,电话语音实时识别。FunASR有两个识别引擎,离线识别 和 实时识别。 离线识别引擎,主要用途是对录音文件进行转写,得到文本结果。 典型的使用场景:会议录音…

启航杯writeup

启航杯writeup 一、web 1.Easy_include题解打开网址得到php代码,发现存在可以通过伪协议来绕过过滤​ 2.构造伪协议 ​ 命令会反向输出所有以fl开头的文件内容输出得到的内容。 ?file=data://text/plain,<?=system(tac fl*);?>​ 3.得到flag2.PCR(文件上传请求)…

使用ArgoCD管理Kubernetes部署指南

对于寻求利用云原生技术力量的组织来说,高效管理 Kubernetes 部署至关重要。ArgoCD 是一款针对 Kubernetes 的声明式 GitOps 持续交付工具,它是一种强大的解决方案。它有助于根据存储在 Git 存储库中的配置自动部署应用程序,从而使 Kubernetes 集群中的应用程序状态与 Git 中…

DeepC2—基于DeepSeek的C2平台

蹭个DeepSeek热点最近DeepSeek很火,蹭个热点,前几天搞了个自动生成工具的网站,有模有样吧,作用的话看看就行,网上绝大部分所谓的Agent也就这样...

3.19 CW 模拟赛 T3. 软件工程

前言 策略肯定是锅了, 基础上需要对策略进行一些修改 喵了个咪的最终还是要针对考试 谢特 某吴姓同学的策略是非常适合我的, 在它的基础上, 我们考虑进行一些本土化 首先花 \(20 \textrm{min}\) 思考每道题, 也就是每道题严格 \(5 \textrm{ min}\) 首先按照能拿到的 \(\rm{subt…

生成AI的两大范式:扩散模型与Flow Matching的理论基础与技术比较

生成模型已成为人工智能领域的关键突破,赋予机器创建高度逼真的图像、音频和文本的能力。在众多生成技术中,扩散模型和Flow Matching尤为引人注目。这两种方法虽然都致力于在噪声与结构化数据之间建立转换,但其基础原理存在本质区别。本文将系统地比较这两种先进技术,深入探…