tomcat的websocket协议升级。如何从报文交换变成全双工通信?session对象的注册和绑定?

WebSocket 读写是通过 Tomcat NIO Connector,但封装后行为是半阻塞式 每个 WebSocket 会话需要绑定一个线程

抛开一堆异常处理过滤这边找到相关代码这个

百度一下

Tomcat 内部通过:

  • WsServerContainer
  • WsWebSocketContainer
  • NIO Connector + Selector

实现了对 WebSocket 的绑定。

每个 Session(一个 WebSocket 会话)最终会绑定到一个 WsRemoteEndpointImplBase,使用 BlockingQueue 来实现消息的写

WebSocketContainer 一个接口

WsWebSocketContainer 这个接口一个实现

connectToServer(...) 用于发起 WebSocket 客户端连接(重载了多个版本)

get/setDefaultAsyncSendTimeout() 设置异步发送消息的最大等待时间(毫秒)

get/setDefaultMaxSessionIdleTimeout() 设置 WebSocket 会话的最大空闲时间(毫秒)

get/setDefaultMaxBinaryMessageBufferSize() 设置默认二进制消息的缓冲区大小(字节)

get/setDefaultMaxTextMessageBufferSize() 设置默认文本消息的缓冲区大小(字符)

getInstalledExtensions() 获取支持的 WebSocket 扩展(如 permessage-deflate)

这个接口定义一些关于任务 后台周期性处理任务

void backgroundProcess();

“在某个时间间隔内自动触发一次的后台任务逻辑”。

setProcessPeriod(int):设置多长时间执行一次。

getProcessPeriod():获取当前设定的周期时间。

我们具体方法实现

两个方法

数据结构来说

链接核心目的在于这个instance发现和被发现。然后这个 instance 类型一个endpoint

前者用于连接到一个已经构造好的 WebSocket 实例(POJO 对象)

后者用于连接到一个 Class 类型的 (这个class类型是一个annotatedEndpointClass 这个标识使用注解接口继承注册客户端实例)WebSocket POJO,交由容器(Tomcat)自己去实例化它

可以看到endpoint 又是session控制单元

再看这两段就比较直接都是传入一个 Endpoint 相关参数

EndpointHolder 传入已实例化的 Endpoint 对象

EndpointClassHolder 传入 Endpoint 类

这一段两个方法

ClientEndpointHolder 对象传入 connectToServerRecursive 这个方法返回一个session对象

这个方法总共150多行这边不做截图

概况一下connectToServerRecursive 方法负责:

  • 解析并检查连接的 URI(ws://wss://
  • 处理代理连接(HTTP CONNECT 方式)
  • 建立底层异步Socket通道连接(AsynchronousSocketChannel
  • 处理 SSL/TLS 握手(如果是 wss)
  • 发送 WebSocket 握手请求(HTTP Upgrade)
  • 处理服务器响应,包括重定向、认证(401)、协议协商、扩展协商
  • 递归处理 HTTP 重定向(最多 20 次)
  • 最终完成 WebSocket 会话的创建并返回

我们关注几个什么代理链接

java net实现一个这样网络代理里面两个成员变量 type 地址

然后这个过程就是简单这个代理对象设置传进来地址类型

逻辑我们可以明确知道整个代理过程不过是合法url写入到代理对象中的地址中去

我们发现有意思 一个目标地址返回一个代理列表为什么

百度一下

因为系统代理机制允许为一个目标地址返回多个候选代理,按优先级排序。这是为了实现灵活的网络路由策略

这里我们不管总之我们只用知道tomcat关注第一个能被循环访问到的可用合法代理对象

关注这里我们http拿到或者没有拿到地址(sa)。还是从方法传参中这个地址(ppst)。这里告诉我们基于http升级websocket协议握手发起tomcat这一层

然后后面一段代码都是这种链接相关的逻辑

包含

为 WebSocket 客户端连接做准备,包括代理处理、请求头构建、连接创建、超时配置、扩展协商等。

我们关注这里这里意味这里二次通信过程就是一个channel(客户端)连接(注册)的起点

通过对这个channel的观察。我们发现这里整个 WebSocket 的连接建立和协议升级过程确实是异步的,通过 Future 来实现异步操作的结果等待(阻塞等待),从而兼顾了非阻塞 I/O 和流程控制的需求。也就是协议升级过程是基于异步回调机制实现的

这里解释

HTTP 重定向(HTTP Redirect)是指服务器在接收到客户端请求后,告诉客户端去访问另一个 URL 地址的机制。

比如

GET http://example.com/oldpage

服务器响应:

HTTP/1.1 301 Moved Permanently

Location: http://example.com/newpage

客户端收到这个响应后,会自动去请求:

GET http://example.com/newpage

我们这里再来一个概念

创建相应的 Transformation 对象链,用于后续 WebSocket 数据的处理。

关注这一方法

先来看一下session数据结构构造器

WsSession wsSession = new WsSession(

clientEndpointHolder, // Endpoint 持有者

wsRemoteEndpointClient, // RemoteEndpoint 发送器

this, // WebSocket 容器(WsWebSocketContainer)

extensionsAgreed, // 协商成功的扩展

subProtocol, // 协商成功的子协议

Collections.emptyMap(), // 路径参数(客户端一般为空)

secure, // 是否 wss

clientEndpointConfiguration // 配置对象

);

WsSession 是一个典型的会话模型,抽象了 WebSocket 在 Java 客户端中的所有核心职责标志报文交换进入全双工标志

然后我们关注方法

我们回忆

关注

总体流程上来说

Channel = AsynchronousSocketChannel.open(...);完成 TCP(或 TLS)连接创建。而后连接的生命周期由 AsyncChannelWrapper 封装后交给 WsSession 与 WsFrameClient 管理。

我们发现连接封装对象作为入参session管理

然后我们不妨探讨一下这个channel上层对象

所以tomcat连接本地读写这样行为都是session一个对象关联

怀疑因为上层可能做到切换session 所以这里就不netty灵活

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值