年轻人还记得KCP吗?什么是KCP,怎么使用呢!!!
年轻⼈还记得KCP吗?什么是KCP,怎么使⽤呢
⼀、什么是KCP
KCP是⼀种⽹络传输协议(A Fast and Reliable ARQ Protocol),可以视它为TCP的代替品,但是它运⾏于⽤户空间,它不管底层的发送与接收,只是个纯算法实现可靠传输,它的特点是牺牲带宽来降低延迟。因为TCP协议的⼤公⽆私,经常牺牲⾃⼰速度来减少⽹络拥塞,它是从⼤局上考虑的。⽽KCP是⾃私的,它只顾⾃⼰的传输效率,从不管整个⽹络的拥塞情况。举个例⼦,TCP检测到丢包的时候,⾸先想到的是⽹络拥塞了,要放慢⾃⼰的速度别让⽹络更糟,⽽KCP想到的赶紧重传别耽误事。
TCP的特点是可靠传输(累积确认、超时重传、选择确认)、流量控制(滑动窗⼝)、拥塞控制(慢开始、拥塞避免、快重传、快恢复)、⾯向连接。KCP对这些参数基本都可配,也没⽤建⽴/关闭连接的过程。
其实KCP并不神秘,因为TCP的⾼度⾃治(很多东西都不可配),满⾜不了如今各种速度需求。⽽KCP就是基于UDP协议,再将⼀些TCP经典的机制移植过来,变成参数可配。
柳州旅游景点⼆、技术特性
RTO翻倍vs不翻倍:TCP超时计算是RTOx2,这样连续丢三次包就变成RTOx8了,⼗分恐怖,⽽KCP启动快速模式后不x2,只是x1.5(实验证明1.5这个值相对⽐较好),提⾼了传输速度。
选择性重传 vs 全部重传:TCP丢包时会全部重传从丢的那个包开始以后的数据,KCP是选择性重传,只重传真正丢失的数据包。
快速重传:发送端发送了1,2,3,4,5⼏个包,然后收到远端的ACK: 1, 3, 4, 5,当收到ACK3时,KCP知道2被跳过1次,收到ACK4时,知道2被跳过了2次,此时可以认为2号丢失,不⽤等超时,直接重传2号包,⼤⼤改善了丢包时的传输速度。
延迟ACK vs ⾮延迟ACK :TCP为了充分利⽤带宽,延迟发送ACK(NODELAY都没⽤),这样超时计算会算出较⼤RTT时间,延长了丢包时的判断过程。KCP的ACK是否延迟发送可以调节。
UNA vs ACK+UNA :ARQ模型响应有两种,UNA(此编号前所有包已收到,如TCP)和ACK(该编号包已收到),KCP有单独ACK,且数据包和ACK包都带UNA信息,有效降低ACK丢失成本。
国家法定节假日2020
⾮退让流控:KCP正常模式同TCP⼀样使⽤公平退让法则,即发送窗⼝⼤⼩由:发送缓存⼤⼩、接收端剩余接收缓存⼤⼩、丢包退让及慢启动这四要素决定。但传送及时性要求很⾼的⼩数据时,可选择通过配置跳过后两步,仅⽤前两项来控制发送频率。以牺牲部分公平性及带宽利⽤率之代价,换取了开着BT都能流畅传输的效果。
还等什么⼩编推荐⾃⼰的linuxC/C++语⾔交流:【】整理了⼀些个⼈觉得⽐较好的学习书籍、视频资料共享在⽂件⾥⾯,有需要的可以⾃⾏添加哦!前100名进领取,额外赠送⼀份价值199的C/C++、linux资料包含(视频教程、电⼦书、实战项⽬及代码)
0是什么意思三、怎么使⽤
KCP只有两个⽂件,分别是ikcp.c和ikcp.h,代码⾏数1300左右。使⽤KCP和使⽤TCP有些不同,所以上⼿之前需要先了解下KCP如何使⽤,需要时间成本。
第⼀步,就是创建⼀个kcp实例,相当于⼀个句柄。
ikcpcb*ikcp_create(IUINT32 conv,void*user)
第⼆步,设置发送数据的接⼝,底层⽤哪种socket都没问题,只要能把数据发送出去,建议使⽤UDP,⽐较简单。
int output(const char*buf,int len, ikcpcb *kcp,void*user)
红烧鱼块的家常做法
第三步,更新KCP状态。KCP运⾏于⽤户空间,所以需要⼿动去更新每个实例的状态,其实主要就是检测哪些数据包该重传了。
void ikcp_update(ikcpcb *kcp, IUINT32 current)
第四步,发送数据。调⽤ikcp_send之后,KCP最后会使⽤上⾯设置的output函数来将发送数据(KCP⾃⼰并不关⼼如何发送数据)。
int ikcp_send(ikcpcb *kcp,const char*buffer,int len)
第五步,预接收数据。先⼿动预接收数据,然后再调⽤ikcp_input将裸数据交给KCP,这些数据有可能是KCP控制报⽂,并不是我们要的数据。
int ikcp_input(ikcpcb *kcp,const char*data,long size)
第六步,接收数据。此时收到的数据才是真正的数据,重组操作在调⽤ikcp_recv之前就完成了。
int ikcp_recv(ikcpcb *kcp,char*buffer,int len)
总体上还是容易理解的,以前我们是直接使⽤各种socket和对端通信,各种功能由⾃⼰控制。现在是
在socket之上使⽤了⼀个中间件KCP,帮忙实现快速可靠传输功能。注意⼀下KCP有模式的区分,不同模式下的速度表现不⼀样,建议把参数配好之后再使⽤,否则使⽤的都是默认的参数。古代女子发髻
四、协议配置
协议默认模式是⼀个标准的 ARQ,需要通过配置打开各项加速开关:
⼯作模式
int ikcp_nodelay(ikcpcb *kcp,int nodelay,int interval,int resend,int nc);
nodelay :是否启⽤ nodelay模式,0不启⽤;1启⽤。
interval :协议内部⼯作的 interval,单位毫秒,⽐如 10ms或者 20ms
ip详细地址查询resend :快速重传模式,默认0关闭,可以设置2(2次ACK跨越将会直接重传)
nc :是否关闭流控,默认是0代表不关闭,1带包关闭。
普通模式:`ikcp_nodelay(kcp, 0, 40, 0, 0); 极速模式: ikcp_nodelay(kcp, 0, 10, 2, 1);
最⼤窗⼝:int ikcp_wndsize(ikcpcb *kcp,int sndwnd,int rcvwnd);该调⽤将会设置协议的最⼤发送窗⼝和最⼤接收窗⼝⼤⼩,默认为32。
最⼤传输单元:纯算法协议并不负责探测 MTU,默认 mtu是1400字节,可以使⽤ ikcp_setmtu来设置该值。该值将会影响数据包归并及分⽚时候的最⼤传输单元。
最⼩RTO:不管是 TCP还是 KCP计算 RTO时都有最⼩ RTO的限制,即便计算出来RTO为40ms,由于默认的 RTO是100ms,协议只有在100ms后才能检测到丢包,快速模式下该值为30ms,可以⼿动更改该值:kcp->rx_minrto =10;
内存分配器
默认KCP协议使⽤ malloc/free进⾏内存分配释放,如果应⽤层接管了内存分配,可以⽤ikcp_allocator来设置新的内存分配器,注意要在⼀开始设置:ikcp_allocator(my_new_malloc, my_new_free);
前向纠错注意
为了进⼀步提⾼传输速度,下层协议也许会使⽤前向纠错技术。需要注意,前向纠错会根据冗余信息解出原始数据包。相同的原始数据包不要两次input到KCP,否则将会导致kcp以为对⽅重发了,这样会产⽣更多的ack占⽤额外带宽。
⽐如下层协议使⽤最简单的冗余包:单个数据包除了⾃⼰外,还会重复存储⼀次上⼀个数据包,以及上上⼀个数据包的内容:
Fn=(Pn,Pn-1,Pn-2)
P0 =(0, X, X)
P1 =(1,0, X)
P2 =(2,1,0)
P3 =(3,2,1)
这样⼏个包发送出去,接收⽅对于单个原始包都可能被解出3次来(后⾯两个包任然会重复该包内容),那么这⾥需要记录⼀下,⼀个下层数据包只会input给kcp⼀次,避免过多重复ack带来的浪费。
五、快在哪⾥
没⽤使⽤任何系统调⽤接⼝
⽆需建⽴/关闭连接(就KCP本⾝来说)
很多影响速度的参数都可配
六、使⽤场景
丢包率⾼的⽹络环境下KCP的优点才会显⽰出来。如果不丢包,那么TCP和KCP的效率不会差别很⼤,可能就是少了连接建⽴/关闭⽽已。⼀般来讲,在公⽹上传输的都可以使⽤,特别是对实时性要求较⾼的程序,如LOL。
七、有何缺点
学习成本
据说有些运营商对UDP有限制?

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。