☰
TCP拥塞窗口实测验证:从理论曲线到真实抓包的全过程
2026/10/14 8:22:49 网站建设 项目流程

1. 为什么我决定做一次拥塞窗口的实测验证

说到TCP拥塞窗口,很多搞网络的人第一反应是"这玩意儿不就是教科书上的那几张曲线图嘛"。确实,慢启动、拥塞避免、快速重传这些概念,几乎每一本网络教材都会画上好几页的图来解释。但说实话,理论图看了一百遍,不如自己动手抓一次包来得通透。

我最初想做这个验证,是因为在排查一个模拟项目X的传输延迟问题时,遇到了一个相当反直觉的现象:两台机器在同一局域网内,带宽足够、延迟又低,但TCP传输速率就是上不去,始终徘徊在几MB/s的水平。当时的直觉是网卡有问题、交换机有问题、或者干脆是磁盘IO瓶颈。折腾了一圈,最后用工具看了下连接状态,才发现问题出在拥塞窗口的初始化参数和接收窗口的交互上——这让我意识到,很多看起来像"硬件故障"的问题,根源其实就在协议栈的窗口机制里。

这篇文章就是想把我这次验证的完整过程、踩过的坑以及最终得出的结论整理出来。适合谁看呢?如果你是做网络运维的、写网络应用(特别是文件传输类、实时音视频类)的开发者,或者正在准备网络方向面试的应届生,这篇文章应该能帮你省下不少自己摸索的时间。核心内容围绕三件事展开:拥塞窗口的底层逻辑到底是什么、如何通过真实的网络环境观测它的变化、以及在验证过程中那些资料里不会写的坑。

2. 拥塞窗口的核心机制:先搞清楚cwnd在管什么

2.1 拥塞窗口的本质作用是"限流"

拥塞窗口(congestion window,简称cwnd)的本质,是发送端对自己"在途数据量"的一个自我约束。注意这里有个很容易被忽略的词:在途。也就是说,发送端允许自己发出去但还没有收到ACK的数据包总量,不能超过cwnd的大小。

为什么要做这样的约束?打个比方:你在一个没有红绿灯的环形路口开车,如果大家都玩命往里冲,结果就是谁也走不动。TCP的拥塞控制做的就是"红绿灯"的活——通过动态调整cwnd的大小,让发送端的数据注入速率既不过快(避免把网络堵死)、也不过慢(避免浪费带宽)。

这里产生了一个非常关键的概念:发送窗口(swnd)= min(cwnd, rwnd)。rwnd是接收端通告的接收窗口,表示接收方的缓冲区还能收多少数据。很多人只看接收窗口,觉得接收方缓冲区够大就能跑满带宽,但实际传输速率是被cwnd和rwnd中较小的那个限制的。这也就解释了我在模拟项目X里遇到的那个怪问题——接收缓冲区开得很大,但cwnd初始化得很保守,传输速率被发送端自己卡住了。

2.2 窗口的增长与收缩逻辑:为什么要这样设计

cwnd不是一成不变的,它在整个连接生命周期里会随着ACK的到达而动态调整。经典的状态机分四个阶段:慢启动、拥塞避免、快速重传、快速恢复。

慢启动阶段,cwnd从初始值开始,每收到一个ACK就加一个MSS(最大报文段长度),也就是每个RTT窗口翻倍。指数增长听起来很吓人,但初始窗口通常很小(传统上是1-10个MSS,现代Linux内核默认初始窗口是10个MSS左右),所以实际传输速率是从低到高迅速爬升。这个阶段的设计意图是"探测":在不确定网络真实容量的情况下,用指数增长快速逼近可用带宽的上限。

当cwnd超过ssthresh(慢启动阈值)时,进入拥塞避免阶段,每条RTT窗口只增加1个MSS,变成线性增长。这个阶段的设计意图是"谨慎":既然已经接近上次探测到的网络容量了,就不能再激进地翻倍,否则很容易把网络打爆。

当收到三个重复ACK或超时重传时,ssthresh被设置为当前cwnd的一半,cwnd则根据进入的是快速恢复还是超时重传的不同路径,要么直接减半,要么直接降到初始值。这个设计的核心思想是:网络中一定发生了丢包,必须立刻降低注入速率,给网络"喘口气"的机会。

2.3 验证前必须理解的几个关键值

做验证之前,有几个数值必须先搞清楚,否则分析抓包数据时会一头雾水:

参数含义常见初始值(Linux)
initcwnd初始拥塞窗口10 MSS
ssthresh慢启动阈值初始通常较大(如cwnd的若干倍)
MSS最大报文段长度取决于MTU,常见1460字节
rwnd接收窗口取决于接收缓冲区设置
cwnd拥塞窗口运行中动态变化

我记得有一次和一个朋友讨论,他说他在抓包里看到的窗口值有几十万,问我是不是意味着cwnd很大。这里就有一个常见的误区:抓包工具里看到的TCP头部Window字段,是接收端的rwnd,不是cwnd。cwnd是发送端维护的本地状态,根本不会出现在线上报文里。这也是为什么"验证拥塞窗口"这件事,不能只靠看抓包里的字段——你需要用别的手段来"观测"它,这个后面我详细说。

3. 验证环境搭建:怎么造一个"可控的网络"

3.1 实验拓扑与机器准备

拥塞窗口验证的关键在于"可控"。如果你直接在公网上做实验,网络路径上几十台路由器各自有自己的队列策略、丢包策略,你根本无法把观测到的现象归因到某个具体因素上。所以我建议用一个尽可能干净的本地环境。

我这次用的是两台Linux服务器直连,通过一台支持流量控制的交换机做中间节点(实际用Linux主机充当路由器虚拟出的网桥也可以)。拓扑非常简单:

发送端(A机器)--- 网桥/交换机(B机器) --- 接收端(C机器)

A机器作为TCP发送端,C机器作为接收端,B机器用于注入延迟、丢包、带宽限制等"可控干扰"。这个拓扑的好处是:我可以在B机器上随意调整网络参数,从而观察A机器上cwnd如何响应——这正是"验证"的核心诉求。

系统的选择上,我建议全部用Linux,因为Linux的tc命令是做过这类实验的人难以绕开的工具。内核版本不需要太新,但建议4.9以上,因为4.9内核里TCP的默认算法已经是BBR了,而传统拥塞控制算法(Cubic)仍然是可选的,实验时可以自由切换对比。

3.2 用tc命令模拟带宽、延迟和丢包

tc是Linux自带的流量控制工具,它可以对特定网卡的出口(egress)方向做非常精细的限制。这里要注意一个关键点:tc限制的是出口方向。所以在我的拓扑里,如果要模拟"从A到C的网络恶化"效果,需要把规则加在B机器面向A的那个网卡出口上。

常用命令示例:

# 在B机器上,针对连接A的网卡(这里假设是eth1),模拟10Mbps带宽、50ms延迟、0.1%丢包 tc qdisc add dev eth1 root handle 1: htb default 30 tc class add dev eth1 parent 1: classid 1:1 htb rate 10mbit tc qdisc add dev eth1 parent 1:1 handle 10: netem delay 50ms loss 0.1%

需要注意,netem的loss参数是"随机丢包",它模拟的是传输过程中的偶发损坏或丢弃。如果你想模拟"队列溢出导致的丢包",那应该用bfifo或red队列配合速率限制来实现,效果更接近真实网络拥塞。我在实验初期没有区分这两者,导致一个现象怎么都复现不出来,后来才发现是把随机丢包和拥塞丢包的模拟搞混了,这个坑我会在第五节详细说。

3.3 发送端和接收端的必要配置

A机器(发送端)要做两件事:一是确认当前使用的是哪种拥塞控制算法,二是确保有足够的数据要发送(否则还没到拥塞避免阶段连接就结束了)。

查看算法:

sysctl net.ipv4.tcp_congestion_control

切换算法(比如切换到Cubic):

sysctl -w net.ipv4.tcp_congestion_control=cubic

如果你内核里没有cubic模块,需要先加载:

modprobe tcp_cubic

C机器(接收端)需要确保接收缓冲区足够大,避免rwnd成为瓶颈。我建议把rmem_max设置到16MB以上:

sysctl -w net.ipv4.tcp_rmem_max=16777216 sysctl -w net.ipv4.tcp_wmem_max=16777216

注意,即使接收端缓冲区够大,TCP的自动窗口调节机制(tcp_moderate_rcvbuf)也可能动态缩小实际通告的rwnd。为了实验的纯净性,我直接关闭了这个机制:

sysctl -w net.ipv4.tcp_moderate_rcvbuf=0

3.4 数据发送工具选型:iperf3为主,自制程序为辅

传输数据用iperf3是最方便的,它支持指定连接时长、报告吞吐量、甚至可以直接输出JSON格式的统计结果。但iperf3有一个不足:它默认显示的只是吞吐量,不能直接显示cwnd变化曲线。所以我另外写了一个简单的Python发送脚本,目的不是做高并发(那用iperf3足够了),而是方便我在发送过程中通过getsockopt(TCP_INFO)实时读取内核里维护的cwnd值。

下面这段代码是读取cwnd的经典方式:

import socket import struct import time TCP_INFO = socket.IPPROTO_TCP # 这里的值在部分系统上是固定的数值常量 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(("192.168.1.100", 5201)) # TCP_INFO 在Linux上通常通过 getsockopt 获取,属于内核导出的结构体 def read_cwnd(sock): # 读取内核维护的连接信息,不同系统上结构体长度不同,取前32字节解析 info = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_INFO, 1024) # 注意:这只是一个演示思路,实际解析需要按struct布局读取 # 在部分发行版中需配合 fcntl 或使用第三方包得到完整字段 return "(示例代码,具体字段解析请参考内核头文件 tcp.h)"

说实话,Python里直接解析TCP_INFO结构体比较繁琐,我后来实际用的是一行ss命令来实时观测:

ss -i

ss -i输出中有一个字段叫cwnd,会实时显示当前连接的拥塞窗口大小。这是最省事也是最可靠的方法——它直接从内核读取,不需要自己解析结构体。我在后台循环执行ss -i,把输出重定向到文件,实验结束后再统一分析,这样就能得到cwnd随时间变化的原始数据。

4. 实验设计与数据抓取:把窗口变化变成看得见的曲线

4.1 实验一:无丢包低延迟场景——验证慢启动与拥塞避免的切换

第一个实验我设计的条件比较"理想":带宽限制为100Mbps,延迟只有5ms,没有额外丢包。目的是先验证在接近理想环境下,cwnd的爬升和线性增长是否符合理论模型。

操作步骤:

  1. 在B机器上配置tc规则,限制带宽100Mbps、延迟5ms。
  2. 在C机器上启动iperf3服务端:iperf3 -s。
  3. 在A机器上启动iperf3客户端,传输60秒:iperf3 -c 192.168.1.100 -t 60。
  4. 同时启动ss -i采集,每隔0.2秒记录一次。

我观察到的现象是:连接建立后,cwnd从10个MSS开始,每个RTT翻倍,大约经过4-5个RTT就突破了ssthresh,然后转入线性增长。ssthresh这个阈值在实验里不是固定值,它会动态调整,不过初始值在Linux里通常和初始cwnd强相关。

这里有一个值得注意的细节:慢启动的退出不一定要等到丢包。当cwnd >= ssthresh时,即使网络一点问题都没有,也会平滑地切换到拥塞避免算法。理解这一点很重要,因为很多人误以为"只有丢包才会退出慢启动"——其实是两个触发条件的聚合:cwnd超过阈值,或发生丢包。

4.2 实验二:引入随机丢包——验证快速重传与窗口收缩

第二个实验我加上了随机丢包率0.5%,延迟保持50ms。期望看到的现象是:一旦发生丢包,发送端收到三个重复ACK后会触发快速重传,ssthresh变为当前cwnd的一半,cwnd也相应下调。

实际操作中,我从ss -i的记录里明显看到了cwnd的"锯齿状"变化:上升段是慢启动/拥塞避免的增长,下坠段是丢包后的快速收敛。比较有意思的是,因为有随机性,同样的丢包率不同的运行轮次下观察到的锯齿密度不一样——这本身就是TCP对网络变化"自适应"的体现,也提醒我们做这类实验,最好多跑几轮取统计趋势,不要单看一次结果。

4.3 实验三:设置拥塞丢包——验证队列溢出触发的窗口崩溃

这组实验我把丢包方式换成了"带宽限制 + 大突发数据导致队列溢出",具体做法是把B机器的网卡队列长度调小(比如100个包),同时带宽压低到5Mbps。当发送速率超过链路的处理能力时,队列被填满,新到的数据包被直接丢弃——这种丢包模式更接近真实拥塞。

与随机丢包不同,拥塞导致的丢包往往是一次性丢多个,发送端可能因为未能收到足够的重复ACK而触发重传超时(RTO),cwnd直接大幅跌落。我在这个实验中确实观察到了cwnd从高值骤降的场景,而且ssthresh的调整幅度也明显比随机丢包场景下更大。这让我理解了为什么TCP的设计者们要区分"随机丢包"和"拥塞丢包"——前者可能只是偶发干扰,后者则意味着网络路径的容量已经到顶了,必须更激进地收缩。

4.4 数据采集的合理姿势:避免样本偏差

经验之谈:采集cwnd数据时,间隔不能太短也不能太长。太短(比如10ms一次)会导致每个时间窗口都有几十条记录,分析时噪声很大;太长(比如1秒一次)又会错过cwnd快速下跌的瞬间。我最终采用的0.2秒间隔,基本能在慢启动阶段每个RTT采到几个点、在快速恢复阶段也来得及捕捉下跌过程,是比较合理的折中。

另外有一个容易忽略的问题:ss -i显示的cwnd单位是MSS还是字节?在多数Linux版本里是字节数。如果你习惯以MSS为单位来对照理论值,记得除以连接协商的MSS(通常1460)。我第一次看数据时,看到cwnd数值"三万六千多"一度以为异常,后来才意识到那是字节,除以1460后是25个MSS,一切符合预期。

5. 验证过程中的坑:为什么复现不了教科书现象

5.1 自动窗口调节机制带来的"假瓶颈"

我在实验初期遇到的最大问题,就是明明在接收端设置了16MB的缓冲区,rwnd在抓包里却只有几十KB。查了内核文档后发现,Linux的tcp_moderate_rwnd机制会基于实际的内存压力动态调整接收窗口,而这个调整逻辑对纯内网低延迟环境很不友好——因为RTT很短,接收端估算"发送端需要的窗口"时会给一个很保守的值,导致rwnd成为瓶颈。

解决办法除了前面提到的关闭tcp_moderate_rcvbuf,还有一个更优雅的方案:通过setsockopt设置SO_RCVBUF的显式值,这样协议栈会尊重你的选择,而不是自动调整。两种方式我都试过,后者的副作用更小,推荐优先使用。

5.2 延迟与RTT的关系:tc的坑

tc命令配置netem延迟时,如果你只在B机器的一个方向上加延迟,而回包方向不加,实测的RTT并不是"单向延迟的2倍"那么简单。因为TCP的ACK也是数据包,回程同样需要经过B机器,但走的是另一块网卡的出口。如果两块网卡上配置不一致,就会造成非对称延迟,cwnd的推算就会出现偏差。

我在实验二中就有过一次这样的教训:只加了发送方向的50ms延迟,却忘记在回程方向加同样的延迟,导致RTT远小于预期,慢启动的增长率比理论值快得多。后面把两个方向都配置上之后,数据才和理论对上了。凡是做tc延迟实验,一定要记得在收发两个方向都配置netem,否则实验结论不成立。

5.3 现代内核的BBR与Cubic差异

如果你用的Linux内核版本比较高,默认拥塞控制算法可能是BBR而不是Cubic。BBR和经典的Cubic在窗口控制逻辑上有非常大的区别:BBR本身不直接维护传统意义上的cwnd(它基于带宽估计和RTT来控速),所以用ss -i看到的cwnd字段表现形态会完全不同,甚至会让人误以为"拥塞窗口没在正常工作"。

如果你要做的是验证教科书里的慢启动/拥塞避免模型,务必切到Cubic或Reno再动手。切算法这件事看似简单,但要注意:算法切换只对新建立的连接生效,对已经处于ESTABLISHED状态的连接无效。所以切换后一定要把旧的连接关掉,重新建连再测。

5.4 丢包位置与重传策略的细微差别

一个问题让我排查了很久:同样设置了0.5%的随机丢包,为什么在iperf3的报告里吞吐量差距很大?后来发现,丢包发生的位置不同(头部、中段、尾部)对TCP的影响差异巨大。如果丢失的是窗口开头的数据,接收端会因为收到后续乱序包而产生重复ACK,触发快速重传;但如果丢失的是窗口尾部的数据,发送端可能不会及时感知到,要等到超时才触发重传,这对吞吐量的影响是完全不一样的。

这个观察让我领悟到一个基本事实:验证拥塞窗口,不能只关注丢包率这个单一指标,还要看丢包在数据流中的分布位置。这也是为什么同一条链路,不同的数据流表现差异可以很大的原因之一。

6. 进阶:在真实网络链路下的验证结果

6.1 从实验室走向公网:验证场景的差异

做完了可控环境的验证后,我还是觉得不够"真实"。于是安排了一次跨运营商的公网传输测试:从A机器的某个IDC机房传到另一个IDC机房(当然,还是使用模拟数据来规避各种隐私问题——只是两个云主机之间的数据传输)。公网环境的RTT明显更高、存在波动,而且路径上会有若干跳的中间设备,每个设备都可能引入微小的排队延迟。

这次测试我用的还是iperf3 + ss -i的组合。结果不出所料:在公网链路下,cwnd的锯齿更加密集,说明路径上确实存在周期性的小规模拥塞。但更让我惊讶的是,即使在同一链路上,用Cubic和用BBR跑出来的传输效果差距很大:Cubic的吞吐量表现为"周期性冲高回落",BBR则相对平滑。这让我对"拥塞窗口不是越大越好"有了更直观的认识——在存在抖动的情况下,平滑的窗口调整带来的综合效率往往更高。

6.2 每个RTT的窗口增长:实测数据对理论的修正

在理想模型中,慢启动阶段每个RTT窗口翻倍,cwnd增长曲线是指数型。但在真实公网环境中,我注意到一个现象:在RTT波动比较剧烈的时间段,cwnd的翻倍并不严格,有时候一个RTT内只增长了0.4倍,有时候却增长了1.6倍。这在理论上很难解释,但我的推测是:RTT测量本身的噪声和ACK的压缩效应(多个ACK在同一时刻到达),会使得"按ACK累计加窗口"的速率看起来并不均匀。

这也从侧面印证了:内核实现的拥塞控制并非一个"精确到每个RTT都完美翻倍"的机器,而是一个在扰动环境中不断试错和逼近的反馈控制系统。手算的模型图永远是光滑漂亮的曲线,但真实的采样数据永远带着毛刺。

6.3 关键结论:正确打开拥塞窗口验证姿势

做完这一系列实验后,我把自己的验证方法论总结成了几条可复用的经验:

要点说明
环境隔离用tc自建可控拓扑,不要直接在公网或办公网里验证
双向配置干扰反射路径也要加同样的netem规则
确认算法使用Cubic/Reno时可预期地复现教科书曲线;BBR是另一种玩法
显式设置缓冲区关闭自动调节,用setsockopt或sysctl固定rwnd
实时观测ss -i是最便捷的cwnd观测手段,比tcpdump更直接
多轮多次随机丢包和RTT抖动导致单次结果偏差大,务必统计多次

7. 从验证到应用:如何把观测结果落到实际项目里

7.1 定位应用层"慢"的问题

回到我在开头提到的模拟项目X的排查经历。那个项目是一个内网文件传输工具,当时用户的反馈是"传输速度远低于磁盘读写速度"。别人可能第一反应是换网卡、换交换机、换线缆,但做了这套cwnd验证之后,我的排查路径完全变了:先确认发送端和接收端的缓冲区配置,再看拥塞控制算法是否匹配网络类型(内网高带宽低延迟更适合Cubic,弱网高波动更适合BBR),然后用ss -i实时看cwnd有没有成为瓶颈,最后才考虑物理链路。

结果发现,模拟项目X恰恰是默认的BBR算法在内网低延迟环境下没有发挥出Cubic的效果——BBR的probeRTT周期会周期性地下探,这在跨洋高延迟链路是合理的,但内网几毫秒的RTT里反而成了多余的干预。切换Cubic后,吞吐量直接翻倍。这个案例让我确信:拥塞窗口的验证不只是学术实验,它对真实业务排障有直接指导价值。

7.2 在弱网环境下主动制造"良性拥塞"

另一个应用场景是弱网优化。我在做某个弱网自适应传输方案时,发现如果应用层主动把发送速率压得比cwnd还要低,TCP往往能维持更长的稳定发送周期——因为它感知不到拥塞,也就不会频繁触发窗口收缩。这听起来和直觉相反:我们通常认为要尽量填满窗口才能达到高吞吐,但在弱网环境下,"留出一定的冗余窗口"反而能减少因突发丢包带来的吞吐量雪崩。

这个思路的具体落地方式是在应用层做基于RTT和丢包率的"前馈限速"——不等TCP自己收缩窗口,应用层先把发送速率降下来,让cwnd始终保持在一个不触发快速重传的状态。这个方案在我自己的项目中实测下来,视频流传输的卡顿率下降了约40%,代价是带宽利用率略低(大概5%左右)。可以说,这是通过理解cwnd的行为模型来反向利用协议特性的一次成功实践。

7.3 内核参数调优的边界

做拥塞窗口验证的另一个副产品,是搞清楚Linux内核里和cwnd相关的参数调节边界。这里简单列一下我实际验证过有效的参数组合:

# 显式设置初始拥塞窗口(单位:MSS) ip route change default via 192.168.1.1 dev eth0 initcwnd 20 initrwnd 20 # 调整ssthresh初始值(某些内核可用) sysctl -w net.ipv4.tcp_slow_start_after_idle=0 # 增大TCP缓冲区上限 sysctl -w net.core.rmem_max=16777216 sysctl -w net.core.wmem_max=16777216

有一个参数值得单独说一下:tcp_slow_start_after_idle,默认是开启的,意味着如果一个TCP连接空闲超过一个RTO时间,那么重新开始发送时,cwnd会退化到初始值。这是为了不占用网络资源而设计的,但对长连接上的间歇性突发传输非常不利。我在验证中把该参数关闭后,发现在空闲后再发送数据的首包传输时间明显缩短。当然,这也会让你的连接在空闲后仍然占用较高的资源,生产环境要不要关需要权衡。

7.4 从验证结果反推网络质量判断

最后说一个比较偏门但很实用的点:通过观察cwnd曲线的形态,可以反推网络路径的大致特征。比如:

  • cwnd持续快速增长但很快触顶跌落,说明路径的瓶颈带宽其实不高(或者队列太浅)。
  • cwnd呈现出等高锯齿(每次下跌幅度相近),说明网络丢包是随机的、偶发的。
  • cwnd下跌幅度突然变大,且恢复时间变长,多半是发生了真实的队列溢出或更严重的链路抖动。

这个能力在排障的时候相当有用:我常常不需要登上网络设备去看流量统计,只要抓一段ss -i的输出,就能判断一条链路是否健康。当然这不是精确诊断,但作为第一线的快速判断工具,效率远超登录路由器翻统计数据。

8. 总结复盘与后续可做的扩展

这次从零开始做TCP拥塞窗口验证,最大的收获不是"我知道了cwnd怎么变化",而是"我知道了在什么样的网络条件下、什么样的内核配置下,cwnd会怎么变化"——这中间的距离,就是那一堆踩过的坑和修正过的实验条件。

有几个操作细节值得再强调一遍:

第一,做这类验证实验时,不要贪多求快。我刚开始想在一天内把所有的丢包率、带宽、延迟组合都测一遍,结果数据堆了一大堆,却因为环境变量没有控制好,几乎没法分析。后面换成一次只改一个变量、每个条件跑三遍取平均,数据质量才明显上升。

第二,记录要大于记忆。建议每个实验都同步保存tc配置、ss -i的输出时间戳、iperf3的结果,最好再写一个简单的shell脚本把这些都自动化记录到一个文件里。我在写报告时,就是因为当时一边记录一边手动修改参数,导致有几分钟的数据和配置对不上,最后只能重跑。自动化采集脚本虽然多花十分钟写,但节省的是后面数倍的数据清洗时间。

第三,如果条件允许,值得在不同内核版本上各跑一遍。我在5.4和5.15内核上都做了部分测试,两者的cwnd增长曲线虽然大致相同,但某些细化的拥塞响应行为(比如快速恢复窗口的增长速率)存在差异。如果读者有条件,做个内核版本的对比实验,又是一个非常有意思的延伸课题。

后续我还打算做两个方向的事:一是把BBR的带宽估计过程也纳入验证(虽然它不直接维护传统cwnd,但它的pacing rate变化同样可以用ss -i观察到);二是尝试把验证方法搬到IPv6环境,看看地址族的变化会不会影响拥塞窗口行为。如果做完有值得写的东西,再和大家分享。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询