WebSocket详解(二):揭开webSocket的神秘面纱

file_5ef8c250bbed4dbaabd6b4e04c824a49.png



在上篇文章《 006 | WebSocket详解(一):初识WebSocket前世今生 》中分享了Socket套接字、通信端点、web1.0、web2.0、表单提交数据、Ajax提交数据、轮训以及longPolling等基础知识,最终引出WebSocket出现的必要性,建议小伙伴还没看的,先去阅读上篇文章。

本篇文章重点分享WebScoket的实现原理。WebSocket是一种在‌浏览器和‌服务器之间进行全双工通信的协议,通过一个长久的、双向的通信通道来实现实时数据传输。WebSocket协议的底层原理包括‌握手、数据帧格式和数据传输三个主要部分。这篇文章我们也只需要搞清楚这三部分即可。

一、websocket通过“握手”过程来建立连接

file_7fb00aa2784c4e72b8457ea6f7ddd5b9.png



这个过程是比较好理解的,客户端发起握手请求(基于http协议发起的),服务端如果支持WebSocket则会响应同意,我们从数据包层面来具体看下这个过程。大家启动webchat,打开控制台,切换到网络请求查看ws请求信息

file_23e564ad1d2d4c56b577030d32d47bd8.png



我们可以在ws下面看到客户端发起了一个特殊http请求:

ws://localhost:8101/ws/chat/{userId}

客户端发起握手请求

这个请求包含了一些特定的HTTP头信息,其中最重要的是Upgrade头,其值设置为websocket,以及Connection头,其值设置为Upgrade。此外,还会包含Sec-WebSocket-Key(一个Base64编码的随机值),用于服务器生成响应中的Sec-WebSocket-Accept

示例HTTP请求头:

GET /ws/chat/{userId}
accept-encoding: gzip, deflate, br, zstd
accept-language: zh-CN,zh;q=0.9,en;q=0.8
cache-control: no-cache
connection: Upgrade
host: localhost:8101
origin: http://localhost:8101
pragma: no-cache
sec-websocket-extensions: permessage-deflate; client_max_window_bits
sec-websocket-key: QPxDgo2xMfQZIwPQ0WM/+w==
sec-websocket-version: 13
upgrade: websocket

服务器响应握手请求

如果服务器同意建立WebSocket连接,它会发送一个HTTP响应,其中包含UpgradeConnection头,确认协议升级和连接保持。服务器还会提供一个Sec-WebSocket-Accept头,其值是客户端Sec-WebSocket-Key的SHA-1散列值,后面加上258EAFA5-E914-47DA-95CA-C5AB0DC85B11,然后再进行Base64编码。

示例HTTP响应头:

connection: upgrade
sec-websocket-accept: lC2Sf4Kzw3KTVQ3M3j/FaaPk2FY=
sec-websocket-extensions: permessage-deflate;client_max_window_bits=15
upgrade: websocket

总结下来,我们在客户端通过new WebSocket()浏览器会发起ws握手请求,服务端如果支持会响应:

new WebSocket("ws://localhost:8101/ws/chat/" + userId);

具体代码详见:/resources/templates/client/chat.html文件,这是webchat pc端对话页面文件,在底部script脚本中先通过loadCurrUserInfo)函数的调用来获取当前登录用户信息,当判断用户登录成功,可以获取到登录用户userId之后调用了initWebSocket()方来在建议websocket链接。

file_5cc07731311f4437a6c78d0eb1efe4bb.png



这里需要注意的是请求websocket建立链接的地址需要时ws:// 或者wss://,两个有什么区别呢,其实同http跟https的区别一样,多出来的这个s时SSL的意思,如果你的服务支持SSL安装证书,拿我们整个网络传输过程是加密安全的,ws也一样,如果服务支持SSL,则需要使用wss:// 来建立链接。

二、数据帧格式

了解完“握手”建立链接过程,来看第二个部分 数据帧传输格式。所以什么是数据帧?如何理解?

WebSocket 协议中的数据帧是 WebSocket 通信的基本单元,用于在客户端和服务器之间传输数据。WebSocket 协议定义了一种二进制格式来封装数据帧,这种格式既高效又灵活,能够支持多种类型的数据传输,包括文本和二进制数据。

比如我们要描述现在的时间,我们会说今天是2024年11月24号23点57分10秒,在这里这个时间就是用户描述日期的基本单元,包括年月日时分秒等几部分的组成。类比websocket的数据帧概念也是一样的,就是用来定义websocket传输数据的一个基本格式/结构,一般会有几部分的组成,方便端点服务更好的理解所传输的数据内容以及传输过程的数据安全性保证等作用。

在 WebSocket 中,数据帧是一段包含特定结构的二进制数据,用于在 WebSocket 连接上传输信息。每个数据帧至少包含以下几个部分:

file_f70af6746742446b816e049bd5bf1268.png



Fin(Final)位:表示帧是否为最后一个片段。如果Fin位为1,则表示这个消息的结束;如果为0,则表示消息还在继续。

RSV1、RSV2、RSV3位:这些位保留给将来的WebSocket协议扩展使用。

Opcode(操作码):表示帧的数据类型或操作类型。WebSocket 协议定义了以下几种操作码:0x0:继续帧(Continuation Frame),用于消息的连续部分。0x1:文本帧(Text Frame),用于传输文本数据。0x2:二进制帧(Binary Frame),用于传输二进制数据。0x3-0x7:保留为非控制帧。0x8:关闭帧(Close Frame),用于关闭连接。0x9:心跳帧(Ping Frame),用于检查连接是否活跃。0xA:Pong帧,响应心跳。0xB-0xF:保留为控制帧。

Mask位:如果这个位为1,表示数据帧的“Payload Data”部分被掩码处理,用于安全传输。

Payload Length:表示“Payload Data”的长度。

Masking-key:如果Mask位为1,这个字段会包含一个32位的掩码密钥,用于解码“Payload Data”。

Payload Data:实际要传输的数据内容。

ps:这部分内容有点枯燥、晦涩难懂,很正常,只是一个知识科普,有一个基本的了解即可。

三、数据传输

客户端和服务端之间的通信是通过交换这些数据帧来完成的。每个数据帧可以包含文本或二进制数据,它们可以独立表示一条消息,也可以是一条消息的片段。

控制帧和非控制帧

WebSocket定义了控制帧和非控制帧。非控制帧用于传输数据,控制帧用于管理连接,如关闭连接、心跳检测等。

数据帧的传输

在WebSocket通信中,数据帧的传输遵循以下步骤:

1.发送端:将消息切割成多个帧,并发送给服务端。

2.接收端:接收消息帧,并将关联的帧重新组装成完整的消息。

ps:为什么消息发送需要分片? WebSocket消息分片主要用于处理大消息、流式数据传输、提高传输效率以及适应网络中间件的行为。通过分片,WebSocket能够更灵活地处理各种数据传输场景。

关闭链接

通过发送特定的控制帧来关闭WebSocket连接。这通常涉及到一个双方都同意的关闭过程,包括发送关闭帧和等待对方确认

ps:这里的内容同样偏特别的底层,了解到这个程度即可。

总结

本篇文章分享了websocket协议最重要的三个部分:通过握手建立协议、websocket数据帧以及数据传输,下篇文章分享在工程中是如何应用、以及工作原理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员盒子技术学院

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值