WebSocket协议

2023-10-30

备注

发送数据强制使用掩码的原因
提供基本的防护,保证每次的消息都是随机的,抵御缓存中毒攻击,但如果运行在SSl/TLS上就没必要了
JS如何发送ping数据帧保活

//这里我们每隔 5 秒钟向服务器发送一个 Ping 帧,
//并带上 type 参数值为 ping 的字符串。服务器收到 Ping 帧后,应该立即回复一个 Pong 帧,
//并包含 type 参数值为 pong 的字符串,以保持连接的活跃。
const webSocket = new WebSocket("wss://example.com");
// 每隔 5 秒钟发送一次 Ping 帧
setInterval(function() {
  if (webSocket.readyState === WebSocket.OPEN) {
    webSocket.send(JSON.stringify({ type: "ping" }), { fin: true, opcode: 0x9 });
  }
}, 5000);

一、什么是WebSocket

  1. 将WebSocket拆开来看,WEB指的是HTTP、Socket指的是套接字调用。那么两个连起来就是WebSocket的含义了。WebSocket就是运行在"Web"上,也就是HTTP上的Socket通信规范,提供与 “TCP” Socket类似的功能,使用它可以像"TCP Socket"一样调用下层协议栈,任意的收发数据。
  2. WebSocket是基于TCP的轻量级网络通信协议,和HTTP属应用层,它俩是平级的。可以理解为TCP OVER WEB

二、为什么要有WebSocket

为了弥补Http协议某方面的缺陷,比如Http2针对队头阻塞引入的多路复用。WebSocket就是为了解决HTTP协议“请求-应答模式”而诞生的。
请求-应答模式的不足:

  1. 是一种"半双工"的通信模式,虽然双方可以都发出数据,但是同一时刻只能收或者发。
  2. 是一种被动的通信模式,服务器端只能被动响应客户端的请求,而无法主动发送数据。虽然后来的Http/2 Http/3新增了Stream、Server Push等特性,但是“应答-请求“仍然是最主要的工作模式。这就导致 HTTP 难以应用在动态页面、即时消息、网络游戏等要求“实时通信”的领域。

在WebSocket出现之前,因为浏览器是一个受限的沙盒环境,不能使用TCP,所以WEB环境开发只能使用Http轮询来模拟实时通信的效果,但是代价大效率低。所以WebSocket就应运而生了,早期是Html5的一部分,后来自立门户,成了一个单独的标准。RFC文档编号是6455

三、WebSocket特点

3.1 全双工

WebSocket是真正“全双工”的通信协议,和TCP一样,客户端和服务端都可以随时向对方发送数据。而不用像Http一样“你拍一我拍一”。这样服务器可以更加主动,一旦有新数据可以推送给客户端,而不用轮询。

3.2 数据传输使用二进制帧

WebSocket 采用了二进制帧结构,语法、语义与 HTTP 完全不兼容,但因为它的主要运行环境是浏览器,为了便于推广和应用,就不得不“搭便车”,在使用习惯上尽量向 HTTP 靠拢,这就是它名字里“Web”的含义。

3.3 服务地址沿用HTTP格式

服务发现方面,WebSocket 没有使用 TCP 的“IP 地址 + 端口号”,而是延用了 HTTP 的 URI 格式,但开头的协议名不是“http”,引入的是两个新的名字:“ws”和“wss”,分别表示明文和加密的 WebSocket 协议。

3.4 默认端口为80和443

因为现在互联网上的防火墙屏蔽了绝大多数的端口,只对 HTTP 的 80、443 端口“放行”,所以 WebSocket 就可以“伪装”成 HTTP 协议,比较容易地“穿透”防火墙,与服务器建立连接。这里的伪装指的是WebSocket利用HTTP的协议升级机制来建立TCP连接,这样就绕过了浏览器沙盒和网络防火墙这些机制。

ws://www.chrono.com
ws://www.chrono.com:8080/srv
wss://www.chrono.com:445/im?user_id=xxx

四、WebSocket的帧结构

WebSocket的侧重点是实时通信,和Http2等侧重于传输效率的协议不同,所以二者的帧也有很大的区别。

  1. WebSocket 虽然有“帧”,但却没有像 HTTP/2 那样定义“流”,也就不存在“多路复用”“优先级”等复杂的特性。
  2. 而它自身就是“全双工”(TCP) 的,也就不需要“服务器推送”。

image.png
数据帧的组成:“结束标志位 + 操作码 + 帧长度 + 掩码”
开头第一个字节

  • 第一位:FIN标志位是消息结束的标志位,相当于 HTTP/2 里的“END_STREAM”,表示数据发送完毕。一个消息可以拆成多个帧,接收方看到“FIN”后,就可以把前面的帧拼起来,组成完整的消息。
  • 第二位到第四位:三个位是保留位,目前没有任何意义,但必须是 0
  • 第五个字节到第八个字节:Opcode操作码,用来标识帧类型。比如1标识帧内容为纯文本,2 表示帧内容是二进制数据,8 是关闭连接,9 和 10 分别是连接保活的 PING 和 PONG。

开头第二个字节

  • 第一位:MASK 掩码标识位,表示帧内容是否使用异或操作(xor)做简单的加密。目前的 WebSocket 标准规定,客户端发送数据必须使用掩码,而服务器发送则必须不使用掩码。
  • 后七位:Payload len 表示帧内容的长度。它是另一种变长编码,最少 7 位,最多是 7+64 位,也就是额外增加 8 个字节,所以一个 WebSocket 帧最大是 2^64。

Payload len字段后的Masking-key

  • 掩码密钥,它是由上面的标志位“MASK”决定的,如果使用掩码就是 4 个字节的随机数,否则就不存在。

五、WebSocket建立连接(握手)的过程

和TCP、TLS一样,WebSocket建立连接也需要先进行握手,然后才能正式收发数据!握手还蹭上了HTTP的便车,利用了Http的协议升级特性来握手,也正是这样才能绕过浏览器沙盒和网络防火墙。

5.1 握手请求阶段

  1. 客户端向服务器发送一个 HTTP GET 请求,并附带 Upgrade 头和 Connection 头,以表明客户端希望升级到 WebSockets 协议。
    1. “Connection: Upgrade”,表示要求协议“升级”;
    2. “Upgrade: websocket”,表示要“升级”成 WebSocket 协议。
  2. 为了防止普通的 HTTP 消息被“意外”识别成 WebSocket,握手消息还增加了两个额外的认证用头字段。
    1. Sec-WebSocket-Key:一个 Base64 编码的 16 字节随机数,作为简单的认证密钥;
    2. Sec-WebSocket-Version:协议的版本号,当前必须是 13。

5.2 握手响应阶段

  1. 确认握手请求没问题后,服务器将生成一个 Sec-WebSocket-Accept 头,该头包含对客户端提供的 Sec-WebSocket-Key 头的加密验证结果,并附带 Upgrade 和 Connection 头。如果浏览器没有接受token,加密验证失败终止握手过程。加密具体的做法是把请求头里“Sec-WebSocket-Key”的值,加上一个专用的 UUID “258EAFA5-E914-47DA-95CA-C5AB0DC85B11”,再计算 SHA-1 摘要 。base64(Sha1(Sec-WebSocket-Key+258EAFA5-E914-47DA-95CA-C5AB0DC85B11))
  2. 服务器将握手响应作为 HTTP 101 状态码和一个 “Switching Protocols” 消息体来返回,标识WebSockets 握手已经成功,服务器与客户端当前正在使用 WebSockets 协议进行通信。
  3. 握手完成后,客户端和服务器之间的连接会保持打开状态,直到其中一个端点发送了一个 CLOSE 帧,或者有网络故障发生,或者超过了连接的时间限制或带宽限制为止。

六、WebSocket应用场景

即时通讯
通过 Websockets 可以实现即时通讯,无需刷新页面。这种应用场景包括在线聊天、多人游戏、实时投票等。
多人协作
对于需要多人协作的应用,Websockets 可以实现实时同步。例如在线文档编辑器、团队协作工具等。
实时数据可视化
Websockets 可以实时更新数据,使得应用可以实现实时数据可视化。这种应用场景包括数据监控、股票交易、实时地图等。
视频和音频流
Websockets 可以传输视频和音频流,使得应用可以实现实时音视频通讯、远程会议、视频直播等。
消息推送和轮询
传统的 HTTP 请求和轮询方式费时费力,而 Websockets 可以实现服务器主动向浏览器推送消息,优化客户端体验。这种应用场景包括新闻订阅、邮件提醒、社交网络消息通知等。
总的来说,Websockets 协议可以为 Web 应用程序提供实时双向通讯的能力,更好的解决了 Web 应用程序实时性的问题,从而实现了更多的创新和应用。

七、WebSocket和SSE对比

Server-Sent Events 是一种基于HTTP相应流实现服务器推送功能的技术

  • 数据交换方式不同 WebSocket 采用双向通信交换数据,而 SSE 采用服务器向客户端单向推送数据。
  • 协议和性能的区别 WebSocket 使用更复杂的协议,需要更多的处理开销,但它具有更低的延迟和更好的性能,可以支持更复杂的应用场景;SSE 的基于 HTTP 的实现方式相对简单,不需要额外的协议,性能相对 WebSocket 稍逊。
  • 安全性 WebSocket 需要专门的服务器端支持,需要处理跨域问题;而 SSE 不需要支持 WebSocket 的服务器端,可以直接在普通的 HTTP 服务器上实现,同时也可以支持跨域请求。
  • 功能适用性 WebSocket 更适用于双向数据传输的应用场景,如即时聊天、游戏等;而 SSE 更适合单向数据推送的场景,如新闻、股票行情、天气预报等。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WebSocket协议 的相关文章

随机推荐