源码角度,分析OkHttp实现WebSocket---握手-保活-数据处理---

本文从源码角度分析了OkHttp实现WebSocket的握手、数据发送与接收、连接保活和关闭过程。WebSocket使用ScheduledThreadPoolExecutor进行数据发送,通过WebSocketWriter组织帧并处理控制消息。数据发送涉及消息队列和BufferedSink,接收端通过消息读取循环处理数据帧。连接保活依赖于PING/PONG帧,关闭连接则通过发送CLOSE帧完成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Streams 是一个 BufferedSource 和 BufferedSink 的 holder:

第三步是调用回调 onOpen()

第四步是初始化 Reader 和 Writer:

OkHttp 使用 WebSocketReader 和 WebSocketWriter 来处理数据的收发。在发送数据时将数据组织成帧,在接收数据时则进行反向擦除,同时处理 WebSocket 的控制消息。

WebSocket 的所有数据发送动作,都会在单线程线程池的线程中,通过 WebSocketWriter 执行。在这里会创建 ScheduledThreadPoolExecutor 用于跑数据的发送操作。

WebSocket 协议中主要会传输两种类型的帧:

  1. 控制帧,主要是用于连接保活的 Ping 帧等;
  2. 数据载荷帧。在这里会根据用户的配置,调度 Ping 帧周期性地发送。我们在调用 WebSocket 的接口发送数据时,数据并不是同步发送的,而是被放在了一个消息队列中。发送消息的 Runnable 从消息队列中读取数据发送。其中会检查消息队列中是否有数据,如果有的话,会调度发送消息的 Runnable 执行。

第五步是配置 socket 的超时时间为 0,也就是阻塞 IO。

第六步执行 loopReader()。这实际上是进入了消息读取循环了,也就是数据接收的逻辑了。

2.2 数据发送

我们可以通过 WebSocket 接口的 send(String text) 和 send(ByteString bytes) 分别发送文本的和二进制格式的消息。

可以看到我们调用发送数据的接口时,做的事情主要是将数据格式化,构造消息,放进一个消息队列,然后调度 writerRunnable 执行。

此外,值得注意的是,当消息队列中的未发送数据,超出最大大小限制,WebSocket 连接会被直接关闭。对于发送失败过或被关闭了的 WebSocket,将无法再发送信息。

在 writerRunnable 中会循环调用 writeOneFrame() 逐帧发送数据,直到数据发完,或发送失败。在 WebSocket 协议中,客户端需要发送 4 种类型的帧:

  1. PING 帧
  2. PONG 帧
  3. CLOSE 帧
  4. MESSAGE 帧

PING 帧用于连接保活,它的发送是在 PingRunnable 中执行的,在初始化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值