美文网首页@IT·互联网
在网络中狂奔:KCP协议

在网络中狂奔:KCP协议

作者: 以镒称铢 | 来源:发表于2020-04-16 03:31 被阅读0次

    在网络中狂奔KCP协议

    一、概述

    TCP保证数据准确交付,UDP保证数据快速到达,KCP则是两种协议的一个折中。

    KCP的设计目标是为了解决在网络拥堵的情况下TCP传输速度慢的问题。

    下面是来自于官网的介绍:

    KCP是一个快速可靠协议,能以比 TCP浪费10%-20%的带宽的代价,换取平均延迟降低 30%-40%,且最大延迟降低三倍的传输效果。纯算法实现,并不负责底层协议(如UDP)的收发,需要使用者自己定义下层数据的发送方式,以 callback的方式提供给 KCP。连时钟都需要外部传递进来,内部不会有任何一次系统调用。

    TCP是为流量设计的(每秒内可以传输多少KB的数据),讲究的是充分利用带宽。而 KCP是为流速设计的(单个数据从一端发送到一端需要多少时间),以10%-20%带宽浪费的代价换取了比 TCP快30%-40%的传输速度。

    KCP力求在保证可靠性的情况下提高传输速度。

    KCP没有规定下层传输协议,但通常使用UDP来实现,至于原因,非常有必要说明,如果不清楚,就不能够真正地了解KCP。

    二、传输协议

    在TCP/IP五层模型协议中,传输协议处在第四层,提供端到端的接口,所以不论是TCP还是UDP,其数据段中都包含了端口号。

    在了解KCP之前,需要先大概清楚TCP和UDP的工作流程,这里从数据段开始讨论,下面是两种协议的数据段格式:

    TCP格式 UDP格式

    补充:传输层的数据叫作段(segment),网络层的数据叫作包(packet),数据链路层的数据叫作帧(frame),物理层的数据叫作流(stream)。

    在网络中,我们认为传输是不可靠的,而在很多场景下我们需要的是可靠的数据,所谓的可靠,指的是数据能够正常收到,且能够顺序收到,于是就有了ARQ协议,TCP之所以可靠就是基于此。

    ARQ协议(Automatic Repeat-reQuest),即自动重传请求,是传输层的错误纠正协议之一,它通过使用确认和超时两个机制,在不可靠的网络上实现可靠的信息传输。

    ARQ协议有两种模式:

    1.停等ARQ协议

    同步请求响应模式,基于超时重传保证可靠。

    停等ARQ协议传输过程

    1>A会为每个即将发送的数据编号,编号的目的是为了标识数据和给数据排序

    2>A发送完数据之后,会给这次发送的数据设置一个超时计时器

    3>B收到数据,将会返回一个确认,该确认也有自己的编号

    4>A收到确认,将删除副本且取消超时计时器,保留副本的原因是传输可能出错

    3>B收到错误的数据,或者数据在传输过程中出错,总之就是说B没有收到想要的数据

    4>A在超时计时器的设置时间内没有收到确认,此时重发数据

    所以可靠的TCP有32位序列号和32位确认号,TCP和UDP都有16位校验和。

    2.连续ARQ协议

    可以连续发送多个分组,而不必每发完一个分组就停下来等待对方确认。

    连续ARQ协议传输过程

    是不是想到了HTTP1.1中的管道模式与HTTP1.0停等模式,但这里有些许区别,HTTP1.1是中服务器按照顺序响应客户端请求,但连续ARQ协议不会响应每个数据段,而是仅仅响应编号最大的这个数据段,表示之前的数据都收到了,这个叫做UNA模式,而停等ARQ协议可以看作是ACK模式。

    现在已经能够在不可靠的网络中传输可靠的数据,但这不意味着可以随意发送数据,带宽是有限的,接收方的负载也是有限的,所以引入了窗口协议,做流量控制。

    窗口协议中有两种:

    1.拥塞窗口

    防止过多的数据注入到网络中,这样可以使网络中的路由器 和链路不至于过载。与拥塞控制相关的有慢启动、退半避让、快重传、快恢复等。慢启动是在刚开始发送数据时让窗口缓慢扩张,退半避让是在网络拥堵时窗口大小减半,快重传是在网络恢复时及时给予响应,与之配合的就是快恢复。

    2.滑动窗口

    接收方告知发送方自己可以接收缓冲区的大小,通常与连续ARQ协议配合使用。

    TCP协议中的16位窗口大小就是为窗口协议提供支持的。而UDP协议的目标是尽最大努力交付,不管你收到没有,所以没有该字段。

    TCP协议是面向连接的协议,在数据传输前通过三次握手建立连接,传输完成后通过四次挥手断开连接,整个过程表示一次完整的数据传输,所以需要4位头长告知哪些是正在传输的数据。

    UDP协议是无连接的,两次数据传输没有任何联系,所以需要16位长度告知本次传输的数据有多少。同时注意,UDP协议每次传输的数据量并不是2^16 - 1 - 8 - 20(8表示UDP头长,20表示IP头长),而是与MTU有关,即数据链路层的最大传输单元(Maximum Transmission Unit),值是1500。

    TCP协议中的8位标志位表示不同的功能,例如当SYN = 1时表示建立连接时让ack = seq + 1而不做任何验证,当URG = 1时16位紧急指针生效,紧急指针表示正常数据的起始位置,而之前的数据则表示额外的紧要数据,可以被尽快处理。

    当清楚TCP和UDP的工作流程,KCP就很容易理解了。

    三、KCP协议的特征

    在谈KCP协议的特征前,还是先贴一下KCP协议的数据段格式。

    KCP格式

    1. RTO不翻倍

    RTO(Retransmission-TimeOut)即重传超时时间,TCP是基于ARQ协议实现的可靠性,KCP也是基于ARQ协议实现的可靠性,但TCP的超时计算是RTO*2,而KCP的超时计算是RTO*1.5,也就是说假如连续丢包3次,TCP是RTO*8,而KCP则是RTO*3.375,意味着可以更快地重新传输数据。通过4字节ts计算RTT(Round-Trip-Time)即往返时延,再通过RTT计算RTO,ts(timestamp)即当前segment发送时的时间戳。

    2.选择性重传

    TCP中实现的是连续ARQ协议,再配合累计确认重传数据,只不过重传时需要将最小序号丢失的以后所有的数据都要重传,而KCP则只重传真正丢失的数据。

    3.快速重传

    与TCP相同,都是通过累计确认实现的,发送端发送了1,2,3,4,5几个包,然后收到远端的ACK:1,3,4,5,当收到ACK = 3时,KCP知道2被跳过1次,收到ACK = 4时,知道2被跳过了2次,此时可以认为2号丢失,不用等超时,直接重传2号包,大大改善了丢包时的传输速度。1字节cmd = 81时,sn相当于TCP中的seq,cmd = 82 时,sn相当于TCP中的ack。cmd相当于WebSocket协议中的openCode,即操作码。

    4.非延迟ACK

    TCP在连续ARQ协议中,不会将一连串的每个数据都响应一次,而是延迟发送ACK,即上文所说的UNA模式,目的是为了充分利用带宽,但是这样会计算出较大的RTT时间,延长了丢包时的判断过程,而KCP的ACK是否延迟发送可以调节。

    5. UNA + ACK

    UNA模式参考特征2和特征4,ACK模式可以参考特征3。4字节una表示cmd = 81时,当前已经收到了小于una的所有数据。

    6.非退让流控

    在传输及时性要求很高的小数据时,可以通过配置忽略上文所说的窗口协议中的拥塞窗口机制,而仅仅依赖于滑动窗口。2字节wnd与TCP协议中的16位窗口大小意义相同,值得一提的是,KCP协议的窗口控制还有其它途径,当cmd = 83时,表示询问远端窗口大小,当cmd = 84时,表示告知远端窗口大小。

    4字节conv表示会话匹配数字,为了在KCP基于UDP实现时,让无连接的协议知道哪个是哪个,相当于WEB系统HTTP协议中的SessionID。

    1字节frg表示拆数据时的编号,4字节len表示整个数据的长度,相当于WebSocket协议中的len。

    四、总结

    至于通常使用UDP来实现KCP的原因,我想大家已经有答案了。第一个是UDP的头部相对于TCP的头部来说更小,第二个是KCP相对于TCP来说有太多的冗余功能,这样白白导致了很多不必要的开销。

    KCP协议在视频加速、直播推流、MOBA游戏等场景中更是大放异彩。

    下一篇文章中我会详细讲一下KCP的具体工作流程,且使用一套java版本的kcp代码来具体说明。有任何问题或者发现文章中的错误之处,欢迎私信或者邮箱过来,谢谢。

    --------------------------------

    公众号:以镒称铢

    出自<孙子兵法 · 军形>,故胜兵若以镒称铢,败兵若以铢称镒。胜者之战民也,若决积水于千仞之溪者,形也。

    长按下图二维码关注,你将发现一个不一样的世界,君子引而不发,跃如也~

    相关文章

      网友评论

        本文标题:在网络中狂奔:KCP协议

        本文链接:https://www.haomeiwen.com/subject/cvflvhtx.html