一 KCP
KCP是什么
kcp是由韦一笑开发的一个开源项目
KCP是一个快速可靠协议,能以比 TCP 浪费 10%-20% 的带宽的代价,换取平均延迟降低 30%-40%,且最大延迟降低三倍的传输效果。纯算法实现,并不负责底层协议(如UDP)的收发,需要使用者自己定义下层数据包的发送方式,以 callback的方式提供给 KCP。 连时钟都需要外部传递进来,内部不会有任何一次系统调用。
特性
tcp面向吞吐,最大化利用带宽
kcp面向速度,快速响应
翻了一下文档,kcp所有的优化都是围绕重传进行的
rto优化
tcp中的rto使用来用控制超时重传时间用的,具体细节可以参考这两篇文章TCP/IP之RTO、RTT TCP/IP重传超时--RTO
TCP超时计算是RTOx2,这样连续丢三次包就变成RTOx8了,十分恐怖,而KCP启动快速模式后不x2,只是x1.5(实验证明1.5这个值相对比较好),提高了传输速度。
通过对rto的优化减少重传等待时间
选择重传
TCP丢包时会全部重传从丢的那个包开始以后的数据,KCP是选择性重传,只重传真正丢失的数据包。
减少重传数量
快速重传
发送端发送了1,2,3,4,5几个包,然后收到远端的ACK: 1, 3, 4, 5,当收到ACK3时,KCP知道2被跳过1次,收到ACK4时,知道2被跳过了2次,此时可以认为2号丢失,不用等超时,直接重传2号包,大大改善了丢包时的传输速度。
减少重传等待时间
ack优化
TCP为了充分利用带宽,延迟发送ACK(NODELAY都没用),这样超时计算会算出较大 RTT时间,延长了丢包时的判断过程。KCP的ACK是否延迟发送可以调节。
减少重传等待时间
arq优化
ARQ模型响应有两种,UNA(此编号前所有包已收到,如TCP)和ACK(该编号包已收到),光用UNA将导致全部重传,光用ACK则丢失成本太高,以往协议都是二选其一,而 KCP协议中,除去单独的 ACK包外,所有包都有UNA信息。
ACK+UNA这种方案是为了实现上面的特性,比如如何让发送端知道丢包,进行快速重传。
非退让流控
KCP正常模式同TCP一样使用公平退让法则,即发送窗口大小由:发送缓存大小、接收端剩余接收缓存大小、丢包退让及慢启动这四要素决定。但传送及时性要求很高的小数据时,可选择通过配置跳过后两步,仅用前两项来控制发送频率。以牺牲部分公平性及带宽利用率之代价,换取了开着BT都能流畅传输的效果。
可以先了解下Tcp的拥塞窗口tcp之拥塞窗口 。 而kcp为了速度,可以禁用退让和满启动等导致发送变慢(速度慢不一定吞吐慢,tcp通过各种机制平衡)的特性。
其他参数
mtu
udp传输必然会碰到拆包组包的问题,那么单个包大小多小合适呢,这里可以参考一下UDP中一个包的大小最大能多大?
KCP中默认的包大小是1400,这个配置用在局域网压测比较合适,实际情况可以适当缩小。
窗口大小
作用类似tcp的发送和接收窗口默认32
参考 kcp的流控文档
最小RTO
不管是 TCP还是 KCP计算 RTO时都有最小 RTO的限制,即便计算出来RTO为40ms,由于默认的 RTO是100ms,协议只有在100ms后才能检测到丢包,快速模式下为30ms,可以手动更改该值:
rto的计算方式参考TCP/IP重传超时--RTO
使用参数
- nodelay:控制rto,如果启动会在各个环节减少rto时间
- interval :控制内部逻辑,主要是缓冲区的flash
- resend:快速重传模式,默认0关闭,可以设置2(2次ACK跨越将会直接重传)
- nc:是否关闭流控,默认是0代表不关闭,1代表关闭。
常用参数模式
- 普通模式:ikcp_nodelay(kcp, 0, 40, 0, 0);
- 极速模式:ikcp_nodelay(kcp, 1, 10, 2, 1);
二 FEC
什么是FEC
编码原理
三 如何在KCP中使用FEC纠错
kcp的使用
kcp可以理解为一套协议栈,拥有拆包,组包,流控等功能,但是本身不具备收发能力。
因此业务上需要
- 自行创建套接字
- 收发不可靠数据(可能是无序的,可能是丢包的)
- 把数据送给kcp协议栈
- 通过kcp协议栈获得可靠数据(有序且完整)
kcp + fec
通过上文可以知道,kcp做了很多事情,虽然kcp对丢包超时等情况做了大量优化,但是在一些实时较高的场景(比如游戏)还是难以接受。此时fec就可以和kcp一起使用,利用fec的纠错机制进一步减少重传。
通过kcp的使用流程可知,fec最适合嵌入的位置是2和3之间,如果在把数据送入协议栈之前通过纠错,修复丢包的数据,那么协议栈就会认为数据是完整的,就不会要求发送端重传。
实现
目前已经有将kcp和fec融合的实现
c版本 https://github.com/xtaci/libkcp
go版本 https://github.com/xtaci/kcp-go
四 参数与性能
todo
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。