kcp 介绍与源代码分析_KCP源码分析

本文深入解析KCP协议的源码,详细阐述Input、Recv、Update和Flush四个关键函数的工作流程。Input处理接收到的数据,清除非确认segment并更新状态;Recv合并fragment,将数据送入接收队列;Send将数据分片并插入发送队列;Flush负责发送数据及处理重传。KCP利用滑动窗口机制和拥塞控制策略,确保高效可靠的数据传输。
摘要由CSDN通过智能技术生成

本文为自己的理解,不代表完全正确,如有错误还请批评。

KCP的一些概念性东西这里就不介绍了,感兴趣的同学可以自行谷歌,本文主要分析KCP的源码。

Command

Segment

KCP包头结构

Property

消息发送时: buffer-> snd_queue-> snd_buf

消息接收时:rcv_buf-> rcv_queue-> buffer

所以这里的两个queue只是一个Temp Container,作为变换的中间站。

这里的output就是KCP发送消息时的回调。

Constructor

这个就是UDP的构造

一些重要的函数

KCP函数的调用顺序:Input()-->Recv()-->Update()-->Flush()

Input()

该函数主要功能是处理接收到的数据

首先先解析数据,得到segment的sn,una等数据包头信息。

之后根据una清除掉snd_buf中已经确认接收到的segment(una即表示该seg之前数据包均已收到)

随后根据snd_buf更新snd_una

之后处理cmd,KCP报文分为ACK报文、数据报文、探测窗口报文、响应窗口报文四种。

如果是IKCP_CMD_ACK

首先根据该segment的rtt更新计算kcp的rtt和rto

之后删除掉snd_buf中相应的segment

随后更新snd_una(此时为下一个未确认的segment)

如果是IKCP_CMD_PUSH,需要判断数据报文是否在接收窗口内,如果是则保存ack

收到该cmd需要发送ack,所以需要将sn和ts放入acklist中

如果该seg符合滑动窗口的范围

则将该segment放入rev_buf中,如果rcv_queue的大小小于rcv_wnd(滑动窗口的大小),则将rev_buf符合条件的segment放入rcv_queue中(保证segment序号连续)

如果是IKCP_CMD_WASK

设置probe的值,发送segment时向远端发送相应接收窗口大小。

如果是IKCP_CMD_WINS,直接跳过

如果远端接收状态有更新,则更新本地拥塞窗口的大小。

Recv()

该函数主要功能是用户层面的数据读取

首先合并fragment

如果rcv_queue小于rcv_wnd(接收窗口大小),则将rcv_buf中合适的segment放入rcv_queue中

如果需要告知远端主机窗口大小

Send()

该函数主要功能是将buffer中的数据发送,把要发送的buffer分片成KCP的数据包格式,插入待发送队列中。

当用户的数据超过一个mss(最大分片大小)的时候,会对发送的数据进行分片处理。KCP采用的是流的方式进行分片处理

如果需要发送的数据大小大于mss,则将其拆分为多个segment发送,将其frg至为其相应的序号,序号从count-1开始递减至0,即count-1表示第一个segment,0表示最后一个segment。

Flush()

该函数主要功能是刷新待处理数据,待处理数据包括ack,win probe,push data等等,以及检测snd_buf中的数据是否需要重传

这里将seg的wnd设置为接收窗口的剩余大小,rcv_que是指接收队列中segment的数量

在发送时将需要发送的数据填充到buffer中,如果buffer下次填入的数据量 >mtu,则调用output函数将buffer中的数据发送出去,ouotput函数由用户定义。

如果远端接收窗口大小为0且当前时间超过下次发送窗口探测时间,则

kcp->probe |= IKCP_ASK_SEND,并更新窗口探测时间间隔和下次窗口探测时间。

取拥塞窗口的大小为发送窗口和远端接收窗口的最小值。

在已经发送的segment的数量不超过拥塞窗口大小时将送sed_queue中的segment放入snd_buf中。

遍历snd_buf中的数据:

如果是第一次发送,则设置rto和超时重传时间,并将needsend置为true。

如果超过超时重传的时间,如果启动无延迟模式,则将segment的rto相加,否则将rto/2,并将needsend置为true。

如果启动了快速重传并且该segment被跳过的次数大于resent,则将needsend置为1,并更新该segment的超时重传时间。

如果needsend被置为1,则将该segment发送出去。

发送之后更新ssthresh(拥塞窗口阈值)和cwnd(拥塞窗口大小)。

Check()

该函数主要功能是检查更新时序,主要作用是减少Update()的调用。

NoDelay()

该函数主要功能决定是否启用nodelay模式。

nodelay:是否启用 nodelay模式,0不启用;1启用。

interval:协议内部工作的 interval,单位毫秒,比如 10ms或者 20ms

resend:快速重传模式,默认0关闭,可以设置2(2次ACK跨越将会直接重传)

nc:是否关闭流控,默认是0代表不关闭,1代表关闭。

快速模式的参数是1, 20, 2, 1,正常模式是0, 40, 0, 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值