RUDPClient/CodeX-TODO.md

344 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# KCP 网络底层调整 TODO
## 目标
将当前项目的网络底层从“自写可靠 UDP + ACK/重传/会话”调整为“UDP 承载 KCP + 明确的传输层/会话层/消息层/同步层分层”,避免职责重叠,并为后续的同步优化、重连、监控打基础。
## 当前现状
- `Assets/Scripts/Network/NetworkTransport/ReliableUdpTransport.cs` 已经引入 `Kcp-CSharp.dll`,但主体逻辑仍然是自定义可靠 UDP。
- 当前传输层仍保留以下逻辑:
- 自定义 `Packet`
- 自定义 ACK
- 自定义重传
- 自定义超时会话清理
- 自定义顺序交付
- `NetworkManager -> MessageManager -> ITransport` 的抽象还没有完全收口,接口和实现存在不一致。
- 当前业务链路不是纯 RPC而是
- 登录 / 登出
- 心跳 / 对时
- `PlayerInput` 上行
- `PlayerState` 下行
- 本地预测 / 服务器校正
## 必须调整的内容
### 1. 收口传输层接口
统一 `ITransport` 的职责,避免上层绕过抽象调用不存在的方法。
建议接口至少包含:
- `StartAsync()`
- `Stop()`
- `Connect(...)` 或客户端构造时明确默认远端
- `Send(byte[] data)`
- `SendTo(byte[] data, IPEndPoint target)`,仅服务端或特殊场景需要
- `SendToAll(byte[] data)`,仅服务端广播需要
- `OnReceive`
- `OnConnected`
- `OnDisconnected`
- `OnError`
当前要处理的问题:
- `MessageManager` 调用了 `transport.Send(...)`,但 `ITransport` 中没有定义该接口。
- `ReliableUdpTransport` 当前的 `SendTo(Packet, IPEndPoint)` 与接口 `SendTo(byte[], IPEndPoint)` 不一致。
### 2. 用 KCP 替代自定义可靠 UDP
KCP 接入后,以下能力不应继续由项目侧重复实现:
- ACK 管理
- 重传调度
- 收发序号维护
- 有序交付
- 滑动窗口
因此需要删除或重构以下内容:
- `Assets/Scripts/Network/NetworkTransport/Packet.cs`
- `Assets/Scripts/Network/NetworkTransport/ClientSession.cs` 中基于自定义 seq/ack 的逻辑
- `Assets/Scripts/Network/NetworkTransport/ReliableUdpTransport.cs` 中的:
- `CheckRetransmit`
- `HandleAckPacket`
- 自定义 `PendingAcks`
- 自定义重复包 / 乱序包处理
- 自定义可靠性定时器
### 3. 重建会话层
KCP 模式下需要清晰区分:
- UDP Socket
- KCP Session
- 业务连接状态
建议设计:
- 客户端:
- 单一默认远端
- 单一 `KcpSession`
- 服务端:
-`IPEndPoint + conv` 管理多个 `KcpSession`
- 支持会话建立、心跳超时、断线清理
会话层至少需要管理:
- `conv`
- 远端地址
- 最后活跃时间
- KCP 实例
- 连接状态
- 断开原因
### 4. 将网络线程与 Unity 主线程解耦
当前 `MessageManager.OnTransportReceiveAsync(...)` 直接进入业务 handler而后续 handler 会继续访问:
- `MasterManager`
- `Player`
- `GameObject`
- `UI`
这些逻辑不应该直接在网络接收线程执行。
需要改为:
1. 网络线程收包
2. 解析最小必要信息
3. 投递到线程安全队列
4. 在 Unity `Update()` 中统一分发到业务层
建议新增:
- `MainThreadDispatcher`
-`ConcurrentQueue<Action>`
-`ConcurrentQueue<ReceivedEnvelope>`
### 5. 重新划分消息 QoS
当前所有消息看起来都走同一种可靠传输语义,这对高频同步不合理。
建议至少拆成两类:
- 强可靠消息
- 登录
- 登出
- 房间管理
- 关键系统命令
- 高频同步消息
- `PlayerInput`
- `PlayerState`
- 以后可能的快照、插值状态、非关键位置更新
需要明确一个原则:
- 如果 `PlayerState` 继续走可靠有序流,旧包阻塞会放大延迟。
- 如果 `PlayerInput` 全部严格可靠发送,也可能产生输入堆积。
这部分要结合项目玩法决定:
- 方案 A全部先走 KCP先完成架构收口再做同步优化
- 方案 B命令消息走 KCP同步消息走裸 UDP / 另一条轻量通道
短期建议先用方案 A 收口,后续再细分。
### 6. 重构连接生命周期
需要把“传输连接”与“业务登录状态”分开。
建议生命周期:
1. 创建 UDP Socket
2. 初始化 KCP
3. 连接服务器 / 建立默认会话
4. 开始收包循环和 KCP Update
5. 发送 `LoginRequest`
6. 收到 `LoginResponse` 后进入已登录状态
7. 开始心跳与超时检测
8. 超时或异常时触发断线回调
9. 按需重连
不要再把“收到登录响应才知道默认服务器端点”这种逻辑和连接过程混在一起。
## 建议同步调整的内容
### 1. 对时与发送频率分离
当前 `MovementComponent` 通过修改 `_sendInterval` 来追赶服务器 Tick这会把
- 时钟校正
- 发包频率
- 同步稳定性
绑在一起。
建议改为:
- 固定输入发送频率
- 单独维护客户端与服务端 Tick 偏移
- 在校正阶段使用 replay / reconcile而不是直接依赖发包间隔漂移
### 2. 增加 KCP 参数配置入口
建议支持配置以下参数:
- `NoDelay`
- `Interval`
- `Resend`
- `NC`
- `SndWnd`
- `RcvWnd`
- `MTU`
- `DeadLink`
建议做法:
- 新增 `KcpTransportConfig`
- 客户端和服务端分别可配置
- 支持 Inspector 或 ScriptableObject 配置
### 3. 增加网络观测指标
至少需要输出:
- RTT
- 重传次数
- 待发送队列长度
- 待接收队列长度
- 会话数量
- 最后活跃时间
- 超时断线原因
后续排查“卡顿、抖动、延迟尖刺、重连失败”时会用到。
### 4. 明确服务端广播策略
当前 `SendToAll` 是直接遍历会话广播。接入 KCP 后要明确:
- 广播是否逐会话独立写入
- 广播时是否允许慢连接拖累整体发送
- 广播消息是否需要按类型分优先级
## 推荐实施步骤
### 阶段 1先把抽象收口
1. 调整 `ITransport`,补齐上层真正需要的发送与连接接口。
2.`MessageManager` 只依赖 `ITransport` 暴露的方法,不再假设具体实现细节。
3. 修复当前 `ReliableUdpTransport``ITransport` 的方法签名不一致问题。
4. 让网络层先达到“接口一致、结构可替换”的状态。
交付标准:
- 上层不再直接依赖某个具体 Transport 的额外方法。
- 业务层不关心底层是 UDP 还是 KCP。
### 阶段 2引入 `KcpTransport`
1. 新建 `KcpTransport`,不要在旧的 `ReliableUdpTransport` 上继续打补丁。
2.`UdpClient` 只负责收发原始 UDP 数据报。
3. 每个连接维护一个 `KcpSession`
4. UDP 收包后先交给对应的 KCP 实例 `Input`
5. 周期性驱动 KCP `Update` / `Check`
6. 从 KCP `Recv` 中取出完整业务消息后再触发 `OnReceive`
交付标准:
- 传输层不再维护自定义 ACK/重传逻辑。
- KCP 可以完成完整收发。
### 阶段 3移除旧可靠 UDP 结构
1. 删除或废弃 `Packet.cs`
2. 删除或废弃旧 `ClientSession` 中基于 seq/ack 的缓存和重传代码。
3. 删除 `ReliableUdpTransport` 中的:
- retransmit timer
- ack handler
- packet seq 交付逻辑
4. 保留必要的会话容器与连接生命周期管理。
交付标准:
- 项目中不再同时存在“两套可靠性机制”。
### 阶段 4主线程分发改造
1. 新增线程安全接收队列。
2. 网络线程只负责:
- 收包
- KCP 输入输出
- 基础错误处理
3. Unity 主线程负责:
- 消息分发
- 游戏对象修改
- UI 更新
交付标准:
- 网络消息不会直接在非主线程操作 Unity 对象。
### 阶段 5连接与心跳改造
1. 明确“连接成功”和“登录成功”是两个不同状态。
2. 心跳只承担:
- 存活检测
- RTT / 时间同步
3. 会话超时和断线重连逻辑放在 session manager而不是业务消息处理里。
交付标准:
- 断线、超时、登录失败、重连等状态可以被明确区分。
### 阶段 6同步策略优化
1. 重新评估 `PlayerInput` 是否必须严格可靠。
2. 重新评估 `PlayerState` 是否应使用可靠有序流。
3. 调整客户端预测、回滚、纠正策略。
4. 把对时逻辑从 `_sendInterval` 漂移中拆出来。
交付标准:
- 高频同步场景下不会因为旧包阻塞导致位置明显滞后。
### 阶段 7监控与调试工具补齐
1. 打印会话状态。
2. 输出 RTT、发送队列、丢包、重传等指标。
3. 提供调试开关,避免正式环境日志过多。
交付标准:
- 网络问题可以通过日志和指标定位。
## 推荐新增的结构
建议新增或重命名以下模块:
- `Assets/Scripts/Network/NetworkTransport/KcpTransport.cs`
- `Assets/Scripts/Network/NetworkTransport/KcpSession.cs`
- `Assets/Scripts/Network/NetworkTransport/KcpTransportConfig.cs`
- `Assets/Scripts/Network/NetworkApplication/MainThreadNetworkDispatcher.cs`
建议废弃或重构:
- `Assets/Scripts/Network/NetworkTransport/ReliableUdpTransport.cs`
- `Assets/Scripts/Network/NetworkTransport/ClientSession.cs`
- `Assets/Scripts/Network/NetworkTransport/Packet.cs`
## 验收标准
- 上层只依赖统一的 `ITransport`
- 传输层不再重复实现 ACK / 重传 / 顺序控制。
- 客户端与服务端都能正常建立 KCP 会话。
- 登录、心跳、输入、状态同步链路可正常跑通。
- 非主线程不再直接访问 Unity 对象。
- 会话超时、断线、重连有明确状态与日志。
- 高频移动同步在丢包 / 抖动场景下仍可用。
## 备注
- 当前最不建议的做法,是在现有 `ReliableUdpTransport` 上继续叠加更多 KCP 相关判断。这样会让自定义可靠 UDP 和 KCP 职责长期重叠。
- 正确方向是:先抽象收口,再用新的 `KcpTransport` 替换旧实现。