你了解WebSocket吗?

1.写在前面

前面的博客已经介绍完了HTTP1.0/1.1相关的协议了,这个时候我们继续来了解对应的WebSocket协议

2.Websocket解决什么问题?

如何及时获得更新?从轮询到通知

在这里插入图片描述

Chrome请求列表:分析WebSocket

  • 过滤器
    • 按类型:WS
    • 属性过滤:is:running
  • 表格列
    • Data:消息负载。如果消息为纯文本,则在此处显示。对于二进制操作码,此列将显示操作码的名称和代码。支持以下操作码:Continuation Frame、Binary Frame、Connection Close Frame、Ping Frame 和Pong Frame
    • Length:消息负载的长度(以字节为单位)
    • Time:收到或发送消息的时间
  • 消息颜色
    • 发送至服务器的文本消息为浅绿色
    • 接收到的文本消息为白色
    • WebSocket操作码为浅黄色
    • 错误为浅红色

支持双向通讯的WebSocket

  • Rfc6455(2011.12)

  • 双向细通讯的优劣?

  • 如何管理会话?

  • 如何维持长连接?

  • 兼容HTTP协议 端口复用

  • 支持扩展 如permessage-deflate扩展

    在这里插入图片描述

3.Websocket的约束

WebSocket的成本

  • 实时性与可伸缩性

    • 牺牲了简单性
  • 网络效率与无状态:请求2基于请求1

    • 牺牲了简单性与可见性

    在这里插入图片描述

在这里插入图片描述

长连接的心跳保持

  • HTTP长连接只能基于简单的超时(常见为65秒)
  • WebSocket连接基于ping/pong心跳机制维持。

兼容HTTP协议

  • 默认使用80或者443端口
  • 协议升级
  • 代理服务器可以简单支持

在这里插入图片描述

设计哲学:在Web约束下暴露TCP给上层

  • 元数据去哪了?
    • 对比:HTTP协议头部会存放元数据
    • 由WebSocket上传输的应用层存放元数据
  • 基于帧:不是基于流(HTTP、TCP)
    • 每一帧要么承载字符数据,要么承载二进制数据
  • 基于浏览器的同源策略模型(非浏览器无效)
    • 可以使用Access-Control-Allow-Origin等头部
  • 基于URI、子协议支持同主机同端口上的多个服务

4.WebSocket协议格式

帧格式示意图

  • 红色是2字节必然存在的帧首部

    在这里插入图片描述

数据帧格式:RSV保留值

  • RSV1/RSV2/RSV3:默认为0,仅当使用extension扩展时,由扩展决定其值

    在这里插入图片描述

数据帧格式:帧类型

  • 持续帧

    • 0:继续前一帧
  • 非控制帧

    • 1:文本帧(UTF8)
    • 2:二进制帧
    • 3-7:为非控制帧保留
  • 控制帧

    • 8:关闭帧
    • 9:心跳帧ping
    • A:心跳帧pong
    • B-F:为控制帧保留

    在这里插入图片描述

ABNF描述的帧格式

在这里插入图片描述

5.如何从HTTP升级到WebSocket

URI格式

  • Ws-URI = “ws:” “//” host [“:” port] path [“?” query]
    • 默认的port端口80
  • Wss-URI = “wss:” “//” host [“:” port] path [“?” query]
    • 默认port端口443
  • 客户端提供信息
    • host与port:主机名和端口
    • Shema:是否基于SSL
    • 访问资源:URI
    • 握手随机数:Sec-WebSocket-Key
    • 选择子协议:Sec-WebSocket-Protocol
    • 扩展协议:Sec-WebSocket-Extensions
    • CORS跨域:Origin

建立握手

在这里插入图片描述

如何证明握手被服务器接受?预防意外

  • 请求中的Sec-WebSocket-Key随机数
    • 例如Sec-WebSocket-Key: A1EEou7Nnq6+BBzoAzqWlg==
  • 响应中的Sec-WebSocket-Accept证明值
    • GUID(RFC4122):258EAFA5-E914-47DA-95CA-C5AB0DC85B11
    • 值构造规则:BASE64(SHA1(Sec-WebSocket-KeyGUID))
      • 拼接值:A1EEou7Nnq6+BBZoAZqWlg==258EAFA5-E914-47DA-95CA-C5AB0DC85B11
      • SHA1 值:713f15ece2218612fcadb1598281a35380d1790f
      • BASE 64 值:cT8V7OIhhhL8rbFZgoGjU4DReQ8=
      • 最终头部:Sec-WebSocket-Accept: cT8V7OIhhhL8rbFZgoGjU4DReQ8=

6.传递消息时的编码格式

消息与数据帧

  • Message消息
    • 1条消息由1个或者多个帧组成,这些数据帧属于同一类型
    • 代理服务器可能合并、拆分消息的数据帧
  • Frame数据帧
    • 持续帧
    • 文本帧、二进制帧

非控制帧的消息分片:有序

在这里插入图片描述

数据帧格式:消息内容的长度

  • 消息内容长度组成

    • 应用消息长度
    • 扩展数据长度
  • <=125字节

    • 仅使用Payload len
  • 126至2^16-1

    • Payload len 值为126
    • Extended payload length16为表示长度
  • 216至264-1

    • Payload len值为127
    • Extended payload length共8字节64位表示长度

    在这里插入图片描述

发送消息

  • 确保WebSocket会话处于OPEN状态
  • 以帧来承载消息,一条消息可以拆分多个数据帧
  • 客户端发送的帧必须基于掩码编码
  • 一旦发送或者接收到关闭帧,连接处于CLOSING状态
  • 一旦发送了关闭帧,且接收到关闭帧,连接处于CLOSED状态
  • TCP连接关闭后,WebSocket连接才完全被关闭

7.掩码及其所针对的代理污染攻击

针对代理服务器的缓存污染攻击

在这里插入图片描述

frame-masking-key掩码

  • 客户端消息:MASK为1(包括控制帧)传递32位无法预测的、随机的Masking-key

  • 服务器端消息:MASK为0

    在这里插入图片描述

掩码如何防止缓存污染攻击?

  • 目的:防止恶意页面上的代码,可以经由浏览器构造出合法的GET请求,使得代理服务器可以识别出请求并缓存响应。
  • 强制浏览器执行以下方法:
    • 生成随机的32位frame-masking-key,不能让JS代码猜出(否则可以反向构造)
    • 对传输的包体按照frame-masking-key执行可对称解密的XOR异或操作,使代理服务器不识别
    • 消息编码算法:
      • j = i MOD 4
      • Transformed-octet-i = original-octet-i XOR masking-key-octet-j

8.如何保持会话心跳

心跳帧

  • 心跳帧可以插在数据帧中传输
    • ping帧
      • opcode=9
      • 可以含有数据
    • pong帧
      • opcode=A
      • 必须与ping帧数据相同

在这里插入图片描述

9.如何关闭WebSocket会话

关闭会话的方式

  • 控制帧中关闭帧:在TCP连接之上的双向关闭

    • 发送关闭帧后,不能再发送任何数据
    • 接收到关闭帧后,不再接收任何到达的数据
  • TCP连接意外中断

关闭帧格式

  • opcode=8

  • 可以含有数据,但仅用于解释关闭会话的原因

    • 前2字节为无符号整型

    • 遵循mask掩码规则

      在这里插入图片描述

关闭帧的错误码

错误码含义
1000正常关闭
1001表示浏览器页面跳转或者服务器将要关机
1002发现协议错误
1003接收到不能处理的数据帧(例如某端不能处理二进制消息)
1004预留
1005预留(不能用在关闭帧里)期望但没有接收到错误码
1006预留(不能用在关闭帧里)期望给出非正常关闭的错误码
1007消息格式不符合opcode(例如文本帧里消息没有用UTF8编码)
1008接收到的消息不遵守某些策略(比1003、1009更一般的错误)
1009消息超出能处理的最大的长度
1010客户端明确需要使用扩展,但服务器没有给出扩展的协商信息
1011服务器遇到未知条件不能完成请求
1015预留(不能用在关闭帧里),表示TLS握手失败

10.写在最后

这篇博客对WebSocket协议进行一个简单的介绍,后面我们会继续介绍对应的HTTP2的协议

对于希望在Spring Boot项目中整合高性能的内嵌容器Undertow,并实现WebSocket支持的开发者来说,这份资料《Spring Boot内嵌Undertow:高性能Web服务器创建指南》是不可多得的资源。通过这份指南,开发者可以详细了解如何将Undertow集成到Spring Boot应用中,并充分利用其高性能的特性。 参考资源链接:[Spring Boot内嵌Undertow:高性能Web服务器创建指南](https://wenku.csdn.net/doc/6xmbjw5pmu) 首先,集成Undertow需要添加相应的Maven依赖到项目的pom.xml文件中,如下所示: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> ``` 在添加了依赖之后,Spring Boot会默认使用Undertow作为内嵌服务器。接下来,可以通过实现WebSocketHandler接口来创建WebSocket服务端点: ```java import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), 参考资源链接:[Spring Boot内嵌Undertow:高性能Web服务器创建指南](https://wenku.csdn.net/doc/6xmbjw5pmu)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值