深入浅出网络协议栈TCP/UDP/KCP/QUIC

目录

一.我们要如何才能做到可靠性传输

1.ACK机制

2.重传机制/重传策略

3.序号机制

4.重排机制

5.窗口机制 流量控制 带宽有限

二 UDP和TCP之间爱恨情仇以及新兴的KCP协议!

1.udp和tcp我们应该如何选择

2.udp和tcp的格式对比

3.1 ARQ协议

3.2 ARQ协议---停等式

3.3 ARQ协议---回退帧

3.4ARQ协议---回退n帧

3.5ARQ协议---选择重传

4.1 RTT和RTO

4.2 流量控制

4.3 如何做到流量控制

4.4 发送方何时再继续发送数据

4.5 流量控制小结

5 拥塞控制

6 .1 udp编程模型

6.2 udp并发编程

6.3 udp如何才能做到可靠,kcp协议在哪些方面上有优势

6.4 UDP如何可靠,KCP协议在哪些方面有优势2

7.1 牛逼的KCP协议

7.2 如何使用KCP协议

7.3 KCP源码流程图

7.4 KCP的配置方式

7.5 KCP协议头

7.6 KCP发送数据过程

7.7 kcp发送窗口

7.8    kcp 接收数据过程

​编辑7.9接收窗口

7.10KCP确认包处理流程

7.11 kcp快速确认

7.12 ikcp_inp

7.13 应答列表acklist

7.14 流量控制和拥塞控制

7.15 探测对方接收窗口

三 在项目中集成KCP协议栈!

1. 范例演示

2 如何集成到项目中,参考代码的chat_server.cc和chat_client.cc两个代码实现聊天室功能

3. 如何集成到项目中,参考asio_kcp

四 QUIC协议

1.QUIC前世今生

2.QUIC为什么在应用层实现

3.QUIC协议术语

4.QUIC和TCP对比

5.QUIC报文格式

6.QUIC报文格式-Stream帧1

7.QUIC报文格式-Stream帧2

8.QUIC的特点

9.省略过多内容......................

10.总结


一.我们要如何才能做到可靠性传输

1.ACK机制

ACK 机制即确认机制,是一种在计算机网络通信、消息队列系统等领域广泛应用的机制,用于确认接收方是否已经正确接收了发送方发送的数据,其英文全称为 acknowledgement 。

2.重传机制/重传策略

重传机制:在网络通信中,由于网络拥塞、传输错误、信号干扰或硬件故障等原因,数据包可能会丢失或损坏。重传机制指的是当发送方发送数据包到接收方时,如果接收方没有正确接收到数据包,或者发送方未收到接收方的确认消息,发送方会重新发送该数据包,直到接收方正确接收到为止的整个过程。比如在 TCP 协议中,发送方发送数据后会等待接收方的确认应答(ACK),若未在规定时间收到,就会重传数据 。它有效解决了数据传输的不确定性,是保障网络通信可靠性的关键措施。

重传策略 :为了更高效、合理地实现重传,衍生出了多种重传策略,常见的如下:

①超时重传:发送方发送数据包后启动一个定时器,设定一个重传超时时间(RTO)。如果在 RTO 内没有收到接收方的确认消息,就认为数据包丢失,需要重新发送。比如固定 RTO 超时重传,在发送前设定一个固定的 RTO;动态 RTO 超时重传则会根据网络情况等因素调整 RTO

②快速重传:不是基于时间,而是基于重复确认的重传机制。当发送方连续收到多个(如三个或四个)重复的确认消息时,就认为在之前的传输中可能有数据包丢失,立即重传疑似丢失的数据包,无需等待 RTO 超时,减少重传延迟,提高网络传输效率 。

③选择性确认重传(SACK) :接收端在确认应答中会指定哪些数据包已经收到,哪些还没收到,发送端根据这些信息,有选择地重传丢失的数据,而不是重传所有可能丢失的数据,提升传输效率。

④重复选择性确认重传(D - SACK):接收端通过该策略告知发送方哪些数据包是重复接收的,发送端可据此判断哪些数据包需要重传,能有效处理 ACK 丢失、网络延时等导致的误判重传情况,减少多余的网络传输 

3.序号机制

序号机制是一种通过为数据单元(如数据包、消息、文件块等)分配唯一编号,来管理数据传输顺序、确保完整性和可靠性的机制,广泛应用于网络通信、分布式系统等领域。

4.重排机制

重排机制是一种处理数据单元顺序的机制,用于解决数据在传输或处理过程中出现的乱序问题,确保数据按正确逻辑顺序被处理

5.窗口机制 流量控制 带宽有限

窗口机制、流量控制与带宽有限性是网络通信中相互关联的关键概念,共同作用于数据传输的效率与稳定性。

窗口机制

 

定义

发送方在未收到接收方确认(ACK)的情况下,可连续发送的数据量上限,通常以 “窗口大小” 表示。例如,TCP 中的滑动窗口允许发送方在等待 ACK 时持续发送多个数据包。

作用

提升效率:通过 “流水线” 式传输减少等待时间,充分利用带宽。

流量控制基础:窗口大小由接收方的处理能力(接收缓冲区)和网络状况动态调整。

流量控制

 

定义:接收方通过限制发送方的发送速率,防止自身因处理速度或缓冲区不足导致数据丢失。

与窗口机制的结合

接收窗口(Advertised Window):接收方在 ACK 中告知发送方当前可用的最大窗口大小。例如,接收方缓冲区剩余 10KB,则窗口大小为 10KB,发送方最多发送 10KB 数据后需等待新 ACK。

动态调整:当接收方处理能力下降时(如缓冲区占用过高),通过缩小窗口大小降低发送速率;反之则扩大窗口。

带宽有限性的挑战

 

问题:当网络带宽不足以承载发送方的发送速率时,会导致拥塞(数据包丢失、延迟增加)。

窗口机制与流量控制的应对

避免拥塞:通过窗口大小限制发送速率,使其不超过网络的实际承载能力。例如,若带宽为 10Mbps,RTT 为 100ms,则理论上窗口大小需至少为 (10Mbps × 0.1s) = 1.25MB(带宽延迟积)才能充分利用带宽,过大则可能引发拥塞。

自适应调整:TCP 通过拥塞控制算法(如慢启动、拥塞避免)动态调整窗口大小。当检测到丢包时,窗口减半以降低速率;当网络空闲时,逐渐增加窗口以探测可用带宽。

三者的协同关系

 

目标:在带宽有限的环境下,平衡可靠性与效率。

流程示例

发送方初始以较小窗口试探网络(慢启动)。

接收方根据自身处理能力通告窗口大小(流量控制)。

网络根据拥塞情况隐式反馈(如延迟或丢包),发送方调整窗口(拥塞控制)。

最终窗口大小稳定在 min (接收窗口,拥塞窗口),确保不超出接收方能力和网络带宽。

二 UDP和TCP之间爱恨情仇以及新兴的KCP协议!

1.udp和tcp我们应该如何选择

2.udp和tcp的格式对比

3.1 ARQ协议
ARQ 协议 (Automatic Repeat-reQuest) ,即 自动重传请求 ,是传输层的错误纠正协
议之一,它通过使用确认和超时两个机制,在不可靠的网络上实现可靠的信息传输。
ARQ 协议主要有 3 种模式:
1. 即停等式 (stop-and-wait)ARQ
2. 回退 n (go-back-n)ARQ
3. 选择性重传 (selective repeat)ARQ
3.2 ARQ协议---停等式
停等协议的工作原理如下:
1 、发送方对接收方发送数据包,然后等待接收方回复 ACK 并且开始计时。
2 、在等待过程中,发送方停止发送新的数据包。
3 、当数据包没有成功被接收方接收,接收方不会发送 ACK. 这样发送方在等待一
定时间后,重新发送数据包。
4 、反复以上步骤直到收到从接收方发送的 ACK.
3.3 ARQ协议---回退帧
为了克服停等协议长时间等待 ACK 的缺陷,连续 ARQ 协议会连续发送一组数据包,然后再
等待这些数据包的 ACK
什么是滑动窗口 发送方和接收方都会维护一个数据帧的序列,这个序列被称作窗口。 发送方的
窗口大小由接收方确定 ,目的在于控制发送速度,以免接收方的缓存不够大,而导致溢出,同时控
制流量也可以避免网络拥塞。协议中规定,对于窗口内未经确认的分组需要重传。
回退 N (Go-Back-N,GBN) :回退 N 步协议允许发送方在等待超时的间歇,可以继续发送分
组。所有发送的分组,都带有序号。在 GBN 协议中,发送方需响应以下三种事件:
1 、上层的调用。上层调用相应 send() 时,发送方首先要 检查发送窗口是否已满
2 、接收 ACK 。在该协议中,对序号为 n 的分组的确认采取累积确认的方式,表明接收方已
正确接收到序号 n 以前 ( 包括 n) 的所有分组。
3 、超时。若出现超时,发送方将重传所有已发出但还未被确认的分组
3.4ARQ协议---回退n帧
对于接收方来说,若一个序号为 n 的分组被正确接收,并且按序,则接收方会为该分组返
回一个 ACK 给发送方,并将该分组中的数据交付给上层。在其他情况下,接收方都会丢弃
分组。若分组 n 已接收并交付,那么所有序号比 n 小的分组也已完成了交付。因此 GBN 采用
累积确认是一个很自然的选择。发送方在发完一个窗口里的所有分组后,会检查最大的有
效确认,然后从最大有效确认的后一个分组开始重传。
如上图所示,序号为 2 的分组丢失,因此 分组 2 及之后的分组都将被重传
总结: GBN 采用的技术包括序号、累积确认、检验和以及计时 / 重传。
3.5ARQ协议---选择重传
虽然 GBN 改善了停等协议中时间等待较长的缺陷,但它依旧存在着性能问题。特别
是当窗口长度很大的时候,会使效率大大降低。而 SR 协议通过让发送方仅重传在接
收方丢失或损坏了的分组,从而避免了不必要的重传,提高了效率。
SR 协议下,发送方需响应以下三种事件:
1 、从上层收到数据。当从上层收到数据后,发送方需检查下一个可用于该分组的
序号。若序号在窗口中则将数据发送。
2 、接收 ACK 。若收到 ACK ,且该分组在窗口内,则发送方将那个被确认的分组标记
为已接收。若该分组序号等于基序号,则窗口序号向前移动到具有最小序号的未确
认分组处。若窗口移动后并且有序号落在窗口内的未发送分组,则发送这些分组。
3 、超时。若出现超时, 发送方将重传已发出但还未确认的分组 。与 GBN 不同的是,
SR 协议中的每个分组都有 独立的计时器
SR 协议下,接收方需响应以下三种事件:
( 假设接收窗口的基序号为 4 ,分组长度也为 4)
1 、序号在 [4,7] 内的分组被正确接收。该情况下,收到的分组落在接收方的窗口内,一个 ACK
将发送给发送方。若该分组是以前没收到的分组,则被缓存。若该分组的序号等于基序号 4
则该分组以及以前缓存的序号连续的分组都交付给上层,然后,接收窗口将向前移动。
2 、序号在 [0,3] 内的分组被正确接收。在该情况下,必须产生一个 ACK ,尽管该分组是接收方
以前已确认过的分组。若接收方不确认该分组,发送方窗口将不能向前移动。
3 、其他情况。忽略该分组
对于接收方来说,若一个分组正确接收而不管其是否按序,则接收方会为该分组返回一个 ACK
给发送方。失序的分组将被缓存,直到所有丢失的分组都被收到,这时才可以将一批分组按
序交付给上层。
4.1 RTT和RTO
RTO Retransmission TimeOut )即重传超时时间。
RTT(Round-Trip Time) 往返时延 。表示从发送端发送数据开始,到发送端收到来自
接收端的确认(接收端收到数据后便立即发送确认),总共经历的时延。
由三部分组成:
链路的传播时间( propagation delay
末端系统的处理时间、
路由器缓存中的排队和处理时间( queuing delay
其中,前两个部分的值对于一个 TCP 连接相对固定,路由器缓存中的排队和处理时间会
随着整个网络拥塞程度的变化而变化。 所以 RTT 的变化 在一定程度上 反应网络的拥塞程
4.2 流量控制
双方在通信的时候,发送方的速率与接收方的速率是不一定相等, 如果发送方
的发送速率太快,会导致接收方处理不过来 ,这时候接收方只能把处理不过来
的数据存在缓存区里(失序的数据包也会被存放在缓存区里) 接收缓存
如果缓存区满了发送方还在疯狂着发送数据,接收方只能把收到的数据包丢掉,
大量的丢包会极大着浪费网络资源, 因此,我们需要 控制发送方的发送速率
让接收方与发送方处于一种动态平衡才好。
对发送方发送速率的控制,称之为流量控制。
公平使用带宽 100M 10个 10M左右
4.3 如何做到流量控制
接收方每次收到数据包,可以在发送确定报文的时候,同时告诉发送方自己的缓存区还剩余多少
是空闲的,我们也把缓存区的剩余大小称之为接收窗口大小,用变量win来表示接收窗口的大小。
发送方收到之后,便会调整自己的发送速率,也就是调整自己发送窗口的大小, 当发送方收到接
收窗口的大小为0时, 发送方就会停止发送数据 ,防止出现大量丢包情况的发生。

 
4.4 发送方何时再继续发送数据
当发送方停止发送数据后,该怎样才能知道自己可以继续发送数据?
1. 当接收方处理好数据,接受窗口 win > 0 时, 接收方发个通知报文去通知发送方 ,告诉他可以继续发 送数据了。当发送方收到窗口大于0 的报文时,就继续发送数据。
2. 当发送方收到接受窗口 win = 0 时,这时发送方停止发送报文,并且同时开启一个定时器, 每一段 时间就发个测试报文去询问接收方 ,打听是否可以继续发送数据了,如果可以,接收方就告诉他此时 接受窗口的大小;如果接受窗口大小还是为0 ,则发送方再次刷新启动定时器。
4.5 流量控制小结
1. 通信的双方都拥有两个滑动窗口,一个用于接受数据,称之为接收窗口;一个用于
发送数据,称之为拥塞窗口(即发送窗口)。指出接受窗口大小的通知我们称之为窗口
通告。
2. 接收窗口的大小固定吗? 接受窗口的大小是根据某种算法动态调整的。
3. 接收窗口越大越好吗? 当接收窗口达到某个值的时候,再增大的话也不怎么会减少
丢包率的了,而且还会更加消耗内存。所以接收窗口的大小必须根据网络环境以及
发送发的的拥塞窗口来动态调整。
4. 发送窗口和接收窗口相等吗? 接收方在发送确认报文的时候,会告诉发送发自己的
接收窗口大小,而发送方的发送窗口会据此来设置自己的发送窗口,但这并不意味
着他们就会相等。首先接收方把确认报文发出去的那一刻,就已经在一边处理堆在
自己缓存区的数据了,所以一般情况下 接收窗口 >= 发送窗口
5 拥塞控制
拥塞控制和流量控制虽然采取的动 作很相似,但 拥塞控制与网络的拥 堵情况相关联 而流量控制与接收 方的缓存状态相关联。
6 .1 udp编程模型
6.2 udp并发编程

自己找源码

6.3 udp如何才能做到可靠,kcp协议在哪些方面上有优势
以10%-20%带宽浪费的代价换取了比 TCP快30%-40%的传输速度。
RTO 翻倍 vs 不翻倍:
TCP 超时计算是 RTOx2 ,这样连续丢三次包就变成 RTOx8 ,十分恐怖,而 KCP 启动快
速模式后不 x2 ,只是 x1.5 (实验证明 1.5 这个值相对比较好),提高了传输速度。
RTO=100ms 为例
选择性重传 vs 全部重传:
TCP 丢包时会全部重传从丢的那个包开始以后的数据, KCP 是选择性重传,只重传真
正丢失的数据包。
快速重传( 跳过多少个包马上重传 )(如果使用了快速重传,可以不考虑 RTO )):
发送端发送了 1,2,3,4,5 几个包,然后收到远端的 ACK: 1, 3, 4, 5 ,当收到 ACK3 时, KCP
知道 2 被跳过 1 次,收到 ACK4 时,知道 2 被跳过了 2 次,此时可以认为 2 号丢失,不用
等超时,直接重传 2 号包,大大改善了丢包时的传输速度。 fastresend =2
6.4 UDP如何可靠,KCP协议在哪些方面有优势2
以10%-20%带宽浪费的代价换取了比 TCP快30%-40%的传输速度。
延迟 ACK vs 非延迟 ACK
TCP 为了充分利用带宽,延迟发送 ACK NODELAY- 针对发送的 都没用), 这样超时计算
会算出较大 RTT 时间 ,延长了丢包时的判断过程。 KCP ACK 是否延迟发送可以调节
UNA vs ACK+UNA
ARQ 模型响应有两种, UNA (此编号前所有包已收到,如 TCP )和 ACK (该编号包已收
到),光用 UNA 将导致全部重传,光用 ACK 则丢失成本太高,以往协议都是二选其一,
KCP 协议中, 除去单独的 ACK 包外,所有包都有 UNA 信息
非退让流控
KCP 正常模式同 TCP 一样使用 公平退让法则 ,即发送窗口大小由: 发送缓存大小、接收
端剩余接收缓存大小 、丢包退让及慢启动这四要素决定。但传送及时性要求很高的小
数据时,可选择通过配置跳过后两步,仅 用前两项来控制发送频率 。以牺牲部分公平
性及带宽利用率之代价,换取了开着 BT 都能流畅传输的效果。
7.1 牛逼的KCP协议
kcp 官方: https://github.com/skywind3000/kcp
名词说明
用户数据:应用层发送的数据,如一张图片 2Kb 的数据
MTU :最大传输单元。即每次发送的最大数据, 1500 实际使用 1400
RTO Retransmission TimeOut ,重传超时时间。
cwnd: congestion window ,拥塞窗口,表示发送方可发送多少个 KCP 数据包。与接
收方窗口有关,与网络状况(拥塞控制)有关,与发送窗口大小有关。
rwnd: receiver window, 接收方窗口大小,表示接收方还可接收多少个 KCP 数据包
snd_queue: 待发送 KCP 数据包队列
snd_buf:
snd_nxt: 下一个即将发送的 kcp 数据包序列号
snd_una: 下一个待确认的序列号,即是之前的包接收端都已经收到。
7.2 如何使用KCP协议
1. 创建 KCP 对象: ikcpcb *kcp = ikcp_create(conv, user);
2. 设置发送回调函数(如UDP send 函数): kcp->output = udp_output;
1. 真正发送数据需要调用sendto
3. 循环调用 update ikcp_update(kcp, millisec); // 在一个线程、定时器 5ms/10m 做调 度
4. 输入一个应用层数据包(如UDP收到的数据包) : ikcp_input(kcp,received_udp_packet,received_udp_size);
1. 我们要使用recvfrom接收,然后扔到kcp里面做解析
5. 发送数据: ikcp_send (kcp1, buffer, 8); 用户层接口
6. 接收数据:hr = ikcp_recv( kcp2, buffer, 10); 用户层读取数据
7.3 KCP源码流程图

7.4 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, 10, 0, 0);
普通模式: ikcp_nodelay(kcp, 0, 10, 0, 1); 关闭流控等
极速模式: ikcp_nodelay(kcp, 2, 10, 2, 1) ,并且修改 kcp1 -> rx_ minrto = 10 ; kcp1 -> fastresend = 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.5 KCP协议头
[0,3]conv: 连接号。 UDP 是无连接的, conv 用于表示来自于哪个
客户端。对连接的一种替代
[4]cmd: 命令字。如, IKCP_CMD_ACK 确认命令,
IKCP_CMD_WASK 接收窗口大小询问命令, IKCP_CMD_WINS 接收
窗口大小告知命令,
[5]frg: 分片,用户数据可能会被分成多个 KCP 包,发送出去
[6,7]wnd: 接收窗口大小,发送方的发送窗口不能超过接收方给
出的数值
[8,11]ts: 时间序列
[12,15]sn: 序列号
[16,19]una: 下一个可接收的序列号。其实就是确认号,收到
sn=10 的包, una 11
[20,23]len :数据长度
data: 用户数据,这一次发送的数据长度
7.6 KCP发送数据过程

7.7 kcp发送窗口
snd_wnd :固定大小,默认 32
rmt_wnd:远端接收窗口大小,
默认 32
cwnd :滑动窗口,可变,越小
一次能发送的数据越小
发送速率的控制是:本质是根据
滑动窗口控制把数据从 snd_
_queue 加入到 send_buf
代码案例
	// calculate window size 取发送窗口和远端窗口最小值得到拥塞窗口小
	cwnd = _imin_(kcp->snd_wnd, kcp->rmt_wnd);      // 当rmt_wnd为0的时候, 
	// 如果做了流控制则取配置拥塞窗口、发送窗口和远端窗口三者最小值
	if (kcp->nocwnd == 0) cwnd = _imin_(kcp->cwnd, cwnd);   // 进一步控制cwnd大小, kcp->cwnd拥塞窗口
	// kcp->nocwnd = 1 少了一次_imin_的判断,可以尽量多发送数据

	// move data from snd_queue to snd_buf
    // 从snd_queue移动到snd_buf的数量不能超出对方的接收能力   此时如果
	//  发送那些符合拥塞范围的数据分片
	//  kcp->snd_una = 10
	// cwnd = 3
	// 
	while (_itimediff(kcp->snd_nxt, kcp->snd_una + cwnd) < 0) {
		IKCPSEG *newseg;
		if (iqueue_is_empty(&kcp->snd_queue)) break;
		//  从snd_queue读取segment
		newseg = iqueue_entry(kcp->snd_queue.next, IKCPSEG, node);

		iqueue_del(&newseg->node);
		// 插入到snd buf 发送窗口
		iqueue_add_tail(&newseg->node, &kcp->snd_buf);  // 从发送队列添加到发送缓存
		kcp->nsnd_que--;
		kcp->nsnd_buf++;
		//设置数据分片的属性
		newseg->conv = kcp->conv;
		newseg->cmd = IKCP_CMD_PUSH;
		newseg->wnd = seg.wnd;		// 告知对方当前的接收窗口
		newseg->ts = current;			// 当前时间
		newseg->sn = kcp->snd_nxt++;        // 序号
		newseg->una = kcp->rcv_nxt;			// 告诉对方可以发送的下一个包序号
		newseg->resendts = current;		// 当前发送的时间
		newseg->rto = kcp->rx_rto;		// 超时重传的时间, 重传间隔的时间
		newseg->fastack = 0;			// 是否快速重传
		newseg->xmit = 0; // 重传次数
	}
7.8    kcp 接收数据过程
7.9接收窗口
snd_wnd :固定大小,默认 32
rmt_wnd :远端接收窗口大小,默认
32
cwnd :滑动窗口,可变,越小一次能
发送的数据越小
接收窗口的控制是: recv_queue 的接
收能力,比如默认接收端口为 32 ,如
recv_queue 接收了 32 个包后则接收
窗口为 0 ,然后用户读走了 32 个包,
则接收窗口变为 32
IKCP_CMD_PUSH 命令
7.10KCP确认包处理流程
7.11 kcp快速确认

7.12 ikcp_inp

7.13 应答列表acklist
收到包后将序号,时间戳存储到应答列表。
ikcp_input 函数调用 ikcp_ack_push 存储应答包
ikcp_ack_push ( kcp , sn , ts ); // 对该报文的确认 ACK 报文放入 ACK 列表中
发送应答包
ikcp_flush 函数发送应答包
应答包解析
ikcp_input 函数进行解析,判断 IKCP_CMD_ACK
7.14 流量控制和拥塞控制
RTO 计算(与 TCP 完全一样)
RTT :一个报文段发送出去,到收到对应确认包的时间差。
SRTT(kcp->rx_srtt) RTT 的一个加权 RTT 平均值,平滑值。
RTTVAR(kcp->rx_rttval) RTT 的平均偏差,用来衡量 RTT 的抖动。
多个 rtt 取平均
以单个的值
RTT 100
RTT 60
RTT 80
比如三个 RTT 平均 RTT=80
研究 tcp 协议栈 RTT 计算方法
7.15 探测对方接收窗口
ikcp_flush 发送探测窗口IKCP_CMD_WASK
ikcp_input 函数
cmd == IKCP_CMD_WASK ,标记 kcp->probe |= IKCP_ASK_TELL;
ikcp_flush 回应探测 IKCP_CMD_WINS

三 在项目中集成KCP协议栈!

1. 范例演示
2 如何集成到项目中,参考代码的chat_server.ccchat_client.cc两个代码实现聊天室功能
3. 如何集成到项目中,参考asio_kcp

四 QUIC协议

1.QUIC前世今生
QUIC ,即 快速UDP网络连接 ( Quick UDP Internet Connections ), 是由
Google 提出的实验性网络传输协议 ,位于 OSI 模型传输层。 QUIC 旨在解决
TCP 协议的缺陷,并最终替代 TCP 协议, 以减少数据传输,降低连接建立延
迟时间,加快网页传输速度。
QUIC诞生于2012年
2.QUIC为什么在应用层实现
新的传输层协议通常会经过严格的设计 ,分析和评估可重复的结果,证明候选协议对
现有协议的正确性和公平性,开发新的传输层协议和它在操作系统进行广泛部署之间
通常需要花费数年的时间。
再者,用户与服务器之间要经过许多防火墙、 NAT (地址转换)、路由器和其他中间设
备, 这些设备很多只认 TCP UDP 。如果使用另一种传输层协议,那么就会有可能无法
建立连接或者报文无法转发,这些中间设备会认为除 TCP UDP 协议以外的协议都是不
安全或者有问题的。
3.QUIC协议术语
QUIC 连接 Client Server 之间的通信关心, Client 发起连接, Server 接受连接
流( Stream :一个 QUIC 连接内,单向或者双向的有序字节流。一个 QUIC
接可以同时包含多个 Stream
帧( Frame QUIC 连接内的最小通信单元。一个 QUIC 数据包( packet )中的
数据部分包含一个或多个帧
4.QUIC和TCP对比

5.QUIC报文格式

6.QUIC报文格式-Stream帧1

7.QUIC报文格式-Stream帧2

8.QUIC的特点
1. 连接建立低时延
2. 多路复用
3. 无队头阻塞
4. 灵活的拥塞控制机制
5. 连接迁移
6. 数据包头和包内数据的身份认证和加密
7. FEC前向纠错
8. 可靠性传输
9. 其他
9.省略过多内容......................
10.总结
1. 路由封杀 UDP 443 端口(这正是 QUIC 部署的端口)
2. UDP 包过多,由于 QoS Quality of Service ,服务质量)限定,会被服务器商认
为是攻击, UDP 包被丢弃
3. 无论是路由器还是防火墙目前对 QUIC 都还没做好准备
4. QUIC 有较多的开源库,标准尚未真正落地,对应的开源库没有经过充分的验证,
不建议中小厂商在 QUIC 上完全跟进