| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 网络协议 -> KCP传输总结 -> 正文阅读 |
|
[网络协议]KCP传输总结 |
一、简介KCP是一个快速可靠协议,能以比?TCP浪费10%-20%的带宽的代价,换取平均延迟降低?30%-40%,且最大延迟降低三倍的传输效果。纯算法实现,并不负责底层协议(如UDP)的收发,需要使用者自己定义下层数据包的发送方式,以?callback的方式提供给?KCP。 连时钟都需要外部传递进来,内部不会有任何一次系统调用。 二、相关概念MTU:最大传输单元。即每次发送的最大数据 cwnd:congestion window,拥塞窗口,表示发送方可发送多少个KCP数据包。与接收方窗口有关,与网络状况(拥塞控制)有关,与发送窗口大小有关。 rwnd:receiver window,接收方窗口大小,表示接收方还可接收多少个KCP数据包。 RTT(Round-Trip Time):?往返时延。在计算机网络中它是一个重要的性能指标,表示从发送端发送数据开始,到发送端收到来自接收端的确认(接收端收到数据后便立即发送确认),总共经历的时延。 MSS:(Maximum Segment Size,最大报文长度。 拥塞窗口:指某一源端数据流在一个RTT内可以最多发送的数据包数, 拥塞窗口(cwnd)会随着网络状态的变化而变化。 接收窗口:rcv_nxt(待接收消息序号),rcv_nxt + rcv_wnd(接收窗口大小) 快速重传机制:假如开启KCP的快速重传机制,并且设置了当重复的ACK个数大于resend时候,直接进行重传。 当发送端发送了1,2,3,4,5五个包,然后收到远端的ACK:1,3,4,5。当收到ACK3时,KCP知道2被跳过1次,当收到ACK4的时候,KCP知道2被跳过2次,当次数大于等于设置的resend的值的时候,不用等到超时,可直接重传2号包。这就是KCP的快速重传机制。 拥塞窗口:指某一源端数据流在一个RTT内可以最多发送的数据包数, 拥塞窗口(cwnd)会随着网络状态的变化而变化。 慢启动机制:慢启动也就是控制拥塞窗口从0开始增长,在每收到一个报文段确认后,把拥塞窗口加1。是为了防止拥塞窗口过大引起网络阻塞,还需要设置一个慢机制的的门限(ssthresh即拥塞窗口的阈值)。当拥塞窗口增长到阈值以后,就减慢增长速度,缓慢增长。 三、kcp源码工作流程图? 1.首先通过ikcp_create创建一个kcp传输对象,创建时需要传入会话ID和用户ID,conv为一个表示会话编号的整数,用来标记本次传输会话。用户ID,用户ID作用不大,估计就是标记一下KCP对象是由哪个用户创建,可以传入用户对象,方便内部使用,没有用到可以传0. 2.设置回调函数,kcp→output,kcp数据封装好以后,需要发送到网络上时会调用该接口,如果使用的是UDP传输,就是调用系统接口sendto 3.周期循环调用ikcp_update,ikcp_update是任务处理的中心,主要处理需要发送的数据队列,更新kcp上下文状态,拥塞控制,重传控制。一般是10ms循环调用一次ikcp_update 4.收到一个下层UDP包以后,通过ikcp_input喂给kcp对象进行解析。然后通过 ikcp_recv获取解析后的原始数据。 5.通过 ikcp_send 进行发送数据,kcp对象会自动进行封装和编号,放入待发送的数据队列,当调用ikcp_update时进行发送。 注意:多线程调用KCP对象时,需要考虑线程的安全性。 四、KCP配置1.工作模式 int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc)
普通模式:?ikcp_nodelay(kcp, 0, 40, 0, 0); 极速模式: ikcp_nodelay(kcp, 1, 10, 2, 1); 2、最大窗口设置 int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd); 该调用将会设置协议的最大发送窗口和最大接收窗口大小,默认为32.?这个可以理解为?TCP的?SND_BUF?和?RCV_BUF,只不过单位不一样?SND/RCV_BUF?单位是字节,这个单位是包。 3、最大传输单元: 纯算法协议并不负责探测?MTU,默认?mtu是1400字节,可以使用ikcp_setmtu来设置该值。该值将会影响数据包归并及分片时候的最大传输单元。 4、最小RTO: 不管是?TCP还是?KCP计算?RTO时都有最小?RTO的限制,即便计算出来RTO为40ms,由于默认的?RTO是100ms,协议只有在100ms后才能检测到丢包,快速模式下为30ms,可以手动更改该值:kcp->rx_minrto = 10; 五、工作原理1、协议头解析 0 ? ? ? ? ? ? ? ? ? ? ? ? 4 ? ? ?5 ? ? 6 ? ? ?8 (BYTE) +-------------------+----+----+----+? | ? ? ?conv ? ? ?| cmd | frg | ?wnd |? +-------------------+----+----+----+ ? 8 | ? ? ? ? ts ? ? ? ? | ? ? ? ? ? ? sn ? ? ? ? ? |? +-------------------+----------------+ ?16 | ? ? ? una ? ? ? | ? ? ? ? ? ? len ? ? ? ? ?| +-------------------+----------------+ ? 24 | ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | | ? ? ? ? ? ?DATA (optional) ? ? ? ? ?| | ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | +-------------------------------------+ conv:连接号。UDP是无连接的,conv用于表示来自于哪个客户端。对连接的一种替代 2、数据发送 2.1数据发送准备 ikcp_send(ikcpcb?kcp, const char?buffer, int len) 2.2数据实际发送 KCP会不停的进行update更新最新情况,数据的实际发送在update时进行。发送过程如下图所示: ? 步骤1:待发送队列移至发送队列 如上图中,snd_queue待发送队列中有4个KCP包等待发送,这个时候snd_nxt下一个发送的kcp包序列号为11,snd_una下一个确认的KCP包为9(8已经确认,9,10已经发送但是还没得到接收方的确认)。因为cwnd=5,发送队列中还有2个发送了但是还未得到确认,所以可以从待发送队列中取前面的3个KCP包放入到发送队列中,序列号分别设置为11,12,13。 步骤2:发送发送队列的数据 1、超时重传 2、快速重传 3、选择重传 步骤3:数据发送 2.3数据接收过程 KCP的接收过程是将UDP收到的数据进行解包,重新组装顺序的、可靠的数据后交付给用户。 2.3.1 KCP数据包接收 kcp_input输入UDP收到的数据包。kcp包对前面的24个字节进行解压,包括conv、?frg、?cmd、?wnd、?ts、?sn、?una、?len。根据una,会删除snd_buf中,所有una之前的kcp数据包,因为这些数据包接收者已经确认。根据wnd更新接收端接收窗口大小。根据不同的命令字进行分别处理。数据接收后,更新流程如下所示: ? 1、IKCP_CMD_PUSH数据发送命令 d、kcp_recv函数,用户获取接收到数据(去除kcp头的用户数据)。该函数根据frg,把kcp包数据进行组合返回给用户。 ? 2、IKCP_CMD_ACK数据确认包 正常情况:收到的sn为11,una为12。表示sn为11的已经确认,下一个等待接收的为12。发送队列中,待确认的一个包为11,这个时候snd_una向后移动一位,序列号为11的包从发送队列中删除。 ? 异常情况:如下图所示,sn!=11的情况均为异常情况。sn<11表示,收到重复确认的包,如本来以为丢失的包重新又收到了,所以产生重复确认的包;sn>17,收到没发送过的序列号,概率极低,可能是conv没变重启程序导致的;112,则启动快速重传 ? ? ? ? ? ? ??? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?[ KCP快速确认?] 确认包发送,接收到的包会全部放在acklist中,以IKCP_CMD_ACK包发送出去 3、流量控制和拥塞控制3.1RTO计算(与TCP完全一样) RTT:一个报文段发送出去,到收到对应确认包的时间差。 3.2流量控制 流量控制是点对点的通信量的控制,是一个端到端的问题。总结起来,就是发送方的速度要匹配接收方接收(处理)数据的速度。发送方要抑制自身的发送速率,以便使接收端来得及接收。 KCP的发送机制采用TCP的滑动窗口方式,可以非常容易的控制流量。KCP的头中包含wnd,即接收方目前可以接收的大小。能够发送的数据即为snd_una与snd_una+wnd之间的数据。接收方每次都会告诉发送方我还能接收多少,发送方就控制下,确保自己发送的数据不多于接收端可以接收的大小。 KCP默认为32,即可以接收最大为32*MTU=43.75kB。KCP采用update的方式,更新间隔为10ms,那么KCP限定了你最大传输速率为4375kB/s,在高网速传输大内容的情况下需要调用ikcp_wndsize调整接收与发送窗口。 KCP的主要特色在于实时性高,对于实时性高的应用,如果发生数据堆积会造成延迟的持续增大。建议从应用侧更好的控制发送流量与网络速度持平,避免缓存堆积延迟。(详见参考资料) 3.3拥塞控制(KCP可关闭) KCP的优势在于可以完全关闭拥塞控制,非常自私的进行发送。KCP采用的拥塞控制策略为TCP最古老的策略,无任何优势。完全关闭拥塞控制,也不是一个最优策略,它全是会造成更为拥堵的情况。 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [ 拥塞控制算法?] KCP发生丢包的情况下的拥塞控制策略与TCP Tahoe版本的策略一致。TCP Reno版本已经使用快恢复策略。因此,丢包的情况下,其实KCP拥塞控制策略比TCP更为苛刻。 KCP在发生快速重传,数据包乱序时,采用的是TCP快恢复的策略。控制窗口调整为已经发送没有接收到ack的数据包数目的一半+resent。 注:目前kernel 3.2以上的linux,默认采用google改进的拥塞控制算法,Proportional Rate Reduction for TCP。该算法的主要特点为,的cwnd如下图所示: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? |
|
网络协议 最新文章 |
使用Easyswoole 搭建简单的Websoket服务 |
常见的数据通信方式有哪些? |
Openssl 1024bit RSA算法---公私钥获取和处 |
HTTPS协议的密钥交换流程 |
《小白WEB安全入门》03. 漏洞篇 |
HttpRunner4.x 安装与使用 |
2021-07-04 |
手写RPC学习笔记 |
K8S高可用版本部署 |
mySQL计算IP地址范围 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 11:29:45- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |