5.5 KiB
依赖协议类型
| 协议 | 流/包 | 必达性 | 顺序保证 | 数据正确性 |
|---|---|---|---|---|
| 串口 | 流 | ❌ | ✅ | ❌ |
| RTP(裸) | 包 | ❌ | ❌ | ❌ |
| 以太网帧 | 包 | ❌ | ❌ | ✅ |
| IP(IPv4/IPv6) | 包 | ❌ | ❌ | ❌(IP 协议本身只保证头部完整性,并不保证数据区无损坏) |
| UDP | 包 | ❌ | ❌ | ✅ |
| TCP | 流 | ✅ | ✅ | ✅ |
| USB Bulk | 包 | ✅ | ✅ | ✅ |
| KCP | 包 | ✅ | ✅ | ✅ |
| SCTP(多流) | 包 | ✅ | ✅ | ✅ |
所有数据协议都是这种结构, 可以基于此协议实现(包/流)✅✅✅ 特性的协议
枚举物理特性类型
| 类型 | 特点 | 例子 |
|---|---|---|
| 网络拥堵型 (Congestion-prone) | 数据量接近带宽上限时会拥堵、排队、丢包,延迟增加 | 以太网、IP 网络、交换机/路由器链路 |
| 稳定误码型 (Constant Error Rate) | 错误率稳定,发送速率不影响误码率 | 串口(UART/RS-232)、光纤点对点链路 |
| 高延迟型 (High Latency) | 延迟几乎固定,带宽可能大,但 ACK/重传回路很慢 | 卫星通信、深空探测链路(NASA 深空网络)、洲际光缆 |
| 抖动型 (Jitter-prone) | 传输延迟不稳定,包延迟波动大,适合平均速率控制,不适合严格定时 | 无线链路(4G/5G/Wi-Fi)、共享交换机低优先级端口 |
| 突发丢包型 (Burst Loss) | 丢包连续发生,需 FEC(前向纠错)或交织(Interleaving)抵抗 | 无线广播、多播视频流、光纤瞬间闪断 |
| 自适应速率型 (Rate Adaptive) | 链路带宽动态变化,需快速检测并调整传输速率 | DSL、Wi-Fi(MCS 调制速率变化)、移动蜂窝网络 |
| 半双工限制型 (Half-duplex) | 同一时刻只能收或发,需要收发切换时机,ACK/数据抢占带宽 | 老式对讲机、RS-485 总线、卫星上行/下行同频时分 |
| 多路径干扰型 (Multipath Fading) | 信号多路径到达互相干扰,误码集中在特定时间段,需频率跳变或纠错码 | 移动无线通信、海面反射、建筑反射 |
物理特性抽象
虽然物理特性种类繁杂,但是我们只能应用软件手段,软件手段有以下几种 1.抗差错编码 2.拥塞控制 传输给物理链路数据的 频率,速度,大小等
kcp协议的底层依赖是udp类型的协议,一种无序,分包,非必达,保证数据正确的协议。 其中抗差错编码就可以做在这个底层协议上,外包给别人做。 kcp可以只专注于拥塞控制,对外提供可靠传输
所以这些物理特性总体来看可以看做可靠性和其他特性的关联函数 又分为两类 一类是 误码率与拥塞控制相关, 这是应该控制发包的流速调整方向和相关方向一致 一类是 误码率与拥塞控制无关, 这是应该忽略影响,尽量达到最大流量限制
rto策略 真实使用rto msg->rto 1、kcp->rx_rto 全局的参考 RTO 基准值 是msg->rto初始值 根据网络抖动、均值,更新 实现在static void ikcp_update_ack(ikcpcb *kcp, IINT32 rtt) 2、msg->rto 根据丢包自动增长策略(kcp->nodelay控制) resendts是一个确切的重传时间点 根据 current 和 rto
kcp xmit 记录重传的次数,包括快速重传
kcp快速重传判断机制 ikcp_parse_fastack() 这里面增加 msg->fastack msg->fastack 快速重传权重值 kcp->fastresend; 快速重传阈值,msg->fastack达到这个值就重传一次 kcp->fastlimit 快速重传最大次数
kcp丢包判断机制 每个包都有自己的 msg->rto 倒计时器 如果当前时间 current >= seg->resendts(重传时间戳),就认为确实丢包了
我改成了最大值,使得快速重传无次数限制 const IUINT32 IKCP_FASTACK_LIMIT = -1; // max times to trigger fastack
send 发送是先进队列 再进 snd_buf
recv 发送是先进buf 再进 队列
snd_buf 是 已经发送出去但还没收到 ACK 的包的链表(按 sn 从小到大排序) rev_buf 是 未与rcv_nxt做连接的,非等间隔递增 ACK 的包的链表
// 这三个变量分析 snd_una 含义:最早未被确认(ACK)的发送序号 由ikcp_shrink_buf更新,从snd_buf取出最左边的处理 snd_nxt 含义:下一个要发送的序号 rcv_nxt 含义:接收方期望收到的下一个序号
kcp 回绕问题 KCP 的解决方法 KCP 里所有序号比较都不会直接用 sn1 > sn2 这种逻辑,而是用 _itimediff(a, b) static inline long _itimediff(IUINT32 later, IUINT32 earlier) { return ((IINT32)(later - earlier)); }
KCP 的序号比较是环形空间,假设包延迟或乱序不会超过 2^31 序号跨度(约 21 亿包),那么判断是安全的。