ikcp_update必须每帧或固定间隔(如10ms)调用以驱动重传、ACK和窗口滑动,漏调则数据无法发出;ikcp_input须喂原始UDP包且地址匹配;实时场景需启用ikcp_nodelay并合理配置MTU、窗口等参数。

ikcp_update 必须每帧或固定间隔调用,否则重传不触发
KCP 不是“设好就跑”的黑盒,它内部依赖定时器驱动重传、ACK 响应、窗口滑动。如果漏掉 ikcp_update,哪怕 ikcp_send 成功返回,数据也永远不会真正发出——因为 KCP 还没把待发包组装好、也没检查是否该重传。
- 推荐每 10ms 调用一次:
ikcp_update(kcp, iclock_ms()),其中iclock_ms()返回单调递增毫秒时间戳(可用std::chrono::steady_clock实现) - 不要在收到 UDP 包时才调用——网络抖动会导致 update 间隔拉长,重传延迟飙升
- 多个 KCP 实例共存时,
ikcp_update可批量调用,但每个实例必须传入各自当前时间,不能复用同一时间值
ikcp_input 只能喂原始 UDP 包,且必须来自同一远端地址
ikcp_input 的设计假设是:你已用 recvfrom 收到一个完整、未解密、未拼接、未修改的 UDP 数据报。任何预处理(比如先解密再喂入、或把多个小包合并成一个大 buffer)都会破坏 KCP 的包边界识别和校验逻辑,导致内部状态错乱甚至崩溃。
- 务必保留原始
sockaddr_in地址信息,每个远端 IP:port 对应唯一ikcpcb*实例 - 不能把 A 客户端的包喂给 B 客户端的 KCP 对象——conv 值匹配失败会直接丢弃
- 若需加密,应在
ikcp_input之前、或ikcp_flush之后做,且加解密逻辑必须严格对称
实时场景必须开 ikcp_nodelay,否则默认 100ms flush 间隔会卡顿
默认模式下,KCP 为节省带宽会攒包,直到满 1400 字节或等够 100ms 才调用 ikcp_flush 输出。这对文件传输友好,但对游戏、语音这类低延迟场景就是硬伤——你发了 1 字节,对方要等 100ms 才能收到。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 启用快速模式:
ikcp_nodelay(kcp, 1, 10, 2, 1)—— 参数依次为:启用 nodelay、内部 flush 间隔(ms)、快速重传阈值(ACK 数)、是否关闭流控 - 注意第四个参数:设为 1 表示禁用拥塞控制,适合局域网或可控网络;公网环境建议保留为 0,否则易打爆上行带宽
- 调用
ikcp_nodelay后仍需手动调用ikcp_flush,它只是让 flush 更积极,不是自动发包
超时、重传、窗口参数怎么调才不翻车
KCP 的行为高度依赖几个关键参数,调错一个就会导致吞吐暴跌或延迟飙升。它不像 TCP 那样自动适应网络,所有策略都得你定。
立即学习“C++免费学习笔记(深入)”;
-
ikcp_setmtu要设为实际 UDP 路径 MTU(通常 1400~1500),设太大导致 IP 分片,设太小浪费带宽 -
ikcp_wndsize控制发送/接收窗口大小,默认 32,高丢包网络可调到 128,但会增加内存占用和延迟 -
ikcp_setinterval影响 update 频率精度,一般不用动;真正关键的是你传给ikcp_update的时间戳是否稳定 - 最常被忽略的是
conv:服务端和客户端必须一致,且不能写死0x1234;建议用连接 ID 或 session token 的哈希生成,避免多连接冲突

















