1.如何做到可靠性传输
(1)ACK机制 应答机制
(2)重传机制 网络丢包的话,需要重传
(3)序号机制 发的包有序号,接收端不是按顺序接收的,路由转发可能先收2-1-3包
(4)重排机制 收的包先缓存,然后进行重排
(5)窗口机制 滑动窗口,为了制约发送的数据 等待用户读取数据,然后释放窗口的资源,防止buffer中的数据越界
注:udp在协议栈不会重传
2.udp场景
(1)实时性要求:音视频通话 、游戏(王者荣耀)
(2)节省资源的要求:嵌入式设备(电池供电)、手机状态报告、户外的设备
3.udp可靠性设计
udpsendto(1000)的长度要小于MTU,MTU默认是1500,1500-udp头(8)-20包头-8=1472实际长度 还会有运营商头部,所以总长一般用1400
4.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。
5.KCP使用方式
(1)创建 KCP对象:ikcpcb *kcp = ikcp_create(conv, user);
(2)设置传输回调函数(如UDP的send函数):kcp->output = udp_output;
(2.1)真正发送数据需要调用sendto
(3)循环调用 update:ikcp_update(kcp, millisec);
(4)输入一个应用层数据包(如UDP收到的数据包):
ikcp_input(kcp,received_udp_packet,received_udp_size);
(4.1)我们要使用recvfrom接收,然后扔到kcp里面做解析
(5)发送数据:ikcp_send(kcp1, buffer, 8); 用户层接口
(6)接收数据:hr = ikcp_recv(kcp2, buffer, 10);
6.KCP配置模式
(1)工作模式:int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc)
nodelay :是否启用 nodelay模式,0不启用;1启用。
interval :协议内部工作的 interval,单位毫秒,比如 10ms或者 20ms
resend :快速重传模式,默认0关闭,可以设置2(2次ACK跨越将会直接重传)
nc :是否关闭流控,默认是0代表不关闭,1代表关闭。
普通模式: 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,单位为包
(3)最大传输单元:int ikcp_setmtu(ikcpcb *kcp, int mtu);
kcp协议并不负责探测 MTU,默认 mtu是1400字节
(4)最小RTO:不管是 TCP还是 KCP计算 RTO时都有最小 RTO的限制,即便计算出来RTO为40ms,由于默认的 RTO是100ms,协议只有在100ms后才能检测到丢包,快速模式下为30ms,可以手动更改该值: kcp->rx_minrto = 10;
7.KCP发送数据过程
8.KCP接收数据过程
9.KCP确认包处理流程
10.KCP快速确认
11.流量控制和拥塞控制
RTO计算(与TCP完全一样)
RTT:一个报文段发送出去,到收到对应确认包的时间差。
SRTT(kcp->rx_srtt):RTT的一个加权RTT平均值,平滑值。
RTTVAR(kcp->rx_rttval):RTT的平均偏差,用来衡量RTT的抖动。