TCP流量控制中的滑动窗口大小、TCP字段中16位窗口大小、MTU、MSS、缓存区大小有什么关系?

本文深入解析TCP协议的关键概念,包括MTU、MSS、滑动窗口、流量控制等,阐述了它们如何影响数据在网络中的传输效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MTU: Maximum Transmit Unit ,最大传输单元,即物理接口(数据链路层)提供给其上层(通常是IP层)最大一次传输数据的大小;以普遍使用的以太网接口为例,缺省MTU=1500 Byte,这是以太网接口对IP层的约束,如果IP层有<=1500 byte 需要发送,只需要一个IP包就可以完成发送任务;如果IP层有> 1500 byte 数据需要发送,需要分片才能完成发送,这些分片有一个共同点,即IP Header ID相同。

MSS:Maximum Segment Size ,TCP提交给IP层最大分段大小,不包含TCP Header和 TCP Option,只包含TCP Payload ,MSS是TCP用来限制application层最大的发送字节数。如果底层物理接口MTU= 1500 byte,则 MSS = 1500- 20(IP Header) -20 (TCP Header) = 1460 byte,如果application 有2000 byte发送,需要两个segment才可以完成发送,第一个TCP segment = 1460,第二个TCP segment = 540。


A (MTU 1500) <------Internet ------> (MTU 1492) B

见上图,TCP SYN消息,A 发送给B 的MSS= 1460,告诉B,B发给A最大segment 为1460 byte

TCP SYN消息,B发送给A的MSS= 1452,告诉A,A发给B最大segment 为1452 byte 。

但A最终能一次发给B多大的字节的segment呢??? 我们给它取名为:A_Send_MSS,取决于两个值,一个是B的通告MSS= 1452;另一个是本地物理接口MTU的限制: 1500-20-20 = 1460。取这两者较小的一个值,则
A_Send_MSS = minimum ( 1452, 1460) = 1452

同理可得 
B_Send_MSS = minimum ( 1460,1452)=1452

可以看出这两者最后是相同的,所以可以得到以下结论,通信双方最终的MSS = 双方较小MTU- 40 。



Socket发送和接收缓冲区大小 :按照我的理解,socket将TCP实现细节封装成API,Socket虽然不等于TCP,但TCP的 send_buffer 和 receive_buffer 应该和socket 等同,用C语言的说法,就是指针相同,用通俗语言来说就是,相同的内存地址段。接收缓冲区receive_buffer 大小等同于自己通告的window size; 至于send_buffer 大小会影响application放入发送缓冲区的速率,但是它应该不是瓶颈,所以不再讨论它。


TCP Window Size : 如果A发送给B window size = 8192,意思是:B最多可以连续发送8192 byte 给A,在A ACK这8192 byte之前。那A的这个8192byte 怎么来的呢? 一般来说,8192byte就是A的接收缓区,A_Receive_Buffer= 8192,如果B不小心发送超过8192 byte,如果application没有及时取走,则超过8192 byte 数据可能会因为A_Receive_Buffer满而被丢弃,所以B会严格遵守A的 advertised window size,如果A通告的window = 0,则B一定不会发送数据。

Window Size 占两个byte,最大值为65535,看完下文你会发现它对对方发送速率影响很大。如果window size 是高速网络带宽的瓶颈,可以采用TCP Option scaling window 这个选项。


Persist Timer:  用于周期探测对方advertised window size 是否依然为0的定时器。接上文,如果A通告的window = 0,则B一定不会发送数据。那B会不会一直被动地等下去?大家想象一个这样的场景,如果B一直被动等待,而这时A接收缓冲区已经空了,但是B无法知道,既然A已经告诉我不能再发数据了,那我就乖乖听话不发了;A(女生)不会主动告知B(男生)哈哈,死锁了!

如何破?用 Persist Timer来解锁! 男生B一旦定时器超时,会发一个 Window Probe 消息给女生A,占一个字节,意思是:Are you ready? Do you still love me? 如果A依然很忙,发 window = 0 给男生B,意思是:本姑娘正忙,没空睬侬!男生B再Restart 自己的定时器,定时器超时再次骚扰女生A,一直会等到A发 window > 0 才结束,本姑娘空闲,欢迎随时来稿。于是男生欣喜若狂,继续发送数据,大段大段的情话…


Scaling Window:  位于TCP option里,在TCP SYN时发送scaling window,最大16,即2的16次方;如果对方没有此option,说明对方不支持,我方也要放弃使用。window size 与scaling window 两者相乘即得到TCP 的最大真实 window size = 64K* 64K= 4.29G bytes,比如我在国内发到美国的TCP流量,如果最大window size 是1 G 字节,一梭子就可以打出1G byte,我的1G的尾部数据还没有发完,我的先锋领头字节已经到达对方,然后对方就选择确认,对方已经刷新window size 了,意味着我方不需要停止等待,可以一直这么发送下去,这是一种提高TCP发送速率的一种高效手段。但使用scaling window 有前提的,适合 高速、长管道、丢包率极小


TCP建立连接的本质: A和B告知彼此的第一个发送字节的 初始序列号 ,建立连接后对每一个发送的字节都需要以初始序列号为 原点 进行编号,需要对方来 确认 每一个字节编号都已经成功接收,双方初始序列号是由 OS动态生成的,随机的值 ,一般每个TCP session都会有不一样的初始序列号,占四个字节。


滑动窗口( Slide Window): 为了便于描述,假定A和B的初始序列号都为0,A发1024字节的数据给B,B通告给A的window size = 4096。

对于A来说,最初的slide window 左侧是自己的原点,即初始序列号0,右侧就是 A的初始序列号+ B通告给A的 window size= 4096;

IF
A发出的1024 byte 数据如果没有得到B确认,A的slide window依然是静止的。

Else IF
A发出的1024 byte 数据如果得到B确认,B通告的 window = 3072,说明数据还在TCP接收缓冲区,application没有取走,则A的slide window左侧向右的方向移动1024,右侧依然静止是4096 ( 1024 + 3072)。

Else IF
A发出的1024 byte 数据如果得到B确认,B通告的 window = 4096,说明数据被application取走,则A的slide window左侧向右的方向移动1024,右侧移动到5120 ( 1024 + 4096)。

总结一下,A的slide window 左侧是自己发出,并被对方确认的字节序列号,右侧是左侧+ B通告window size。


TCP流量控制 :TCP三次同步握手建立连接之后,会 采用slow start 算法来快速摸到传输路径带宽的峰值 。为了便于叙述,假定window size 1024 byte = 1 segment,以下全采用segment,slow start 算法如下:

1)无论对方advertised window size 多大,A第一次只发一个TCP segment,即 congestion window =1,等待对方确认

2)收到确认,发2个 Congestion window = 2, 等待对方确认 

3)收到确认,继续加倍,发4个…



就这么指数翻倍,那是不是A可以无穷无尽地增长下去?当然不会,A的发送速率受到两个值制约:

一个是对方的 advertised window size  ,如果此值是8,那A最大一次只能发8个segment,需要等待B的确认,在A等待期间,A到B方向带宽是闲置的,需要至少等待一个 RTT(Round Trip Time),收到B的确认并且 window >= 1024 ,A才可以继续发送。如果网络带宽无限大,网络没有丢包,那带宽的峰值由对方的advertised window size 以及A与B之间RTT来决定。window size 越大,说明对方接收缓冲区越大,A可以最大限度利用带宽,可以让字节流充分占据链路,带宽闲置率低,发送速率也就越高;RTT越小,A的等待时间也相应小一些,但它对A发送速率的影响远没有window size来的大。

另外一个制约值就是 路径实时带宽 ,A方发送速率一直翻倍,终于到达了其最大峰值,此时的congestion window 被保存 到slow start threshold ,再大就开始丢包了,A方没有收到被丢弃包的确认,知道可能触发路径的拥塞,于是启动了另外一个法, congestion avoidance , 先将slow start threshold = 1/2 *slow start threshold,congestion window = slow start threshold +1 , 可以看出A方的发送速率立马就减到峰值的一半,于是以1/2的峰值速率 线性增长。何谓线性增长?就是收到对方确认,每次对 congestion window + 1,如果出现又丢包了,再将发送速率减半,然后在线性增长。这就是TCP特点,速率减少时,指数对半下降;速率上升时,slow start 是指数翻倍上升,而congestion avoidance 是线性增长。

总结一下,slow start虽然字面是慢启动,但是它可以指数翻倍增长,快速上摸到路径的带宽极限值,一旦有丢包,指数1/2下降,特点是大起大落,这不利于带宽的充分利用。

A方啥时采用slow start? 
A_Send_Window < Slow Start Threshold

而congestion avoidance 则是用来克服slow start 的不足,采用小碎步的方式,线性增长逼近带宽的峰值。

A方啥时采用congestion avoidance?

A_Send_Window > Slow Start Threshold




https://www.zhihu.com/question/48454744

<think>好的,我现在需要回答用户关于TCP接收窗口的问题。用户提到想了解接收窗口的定义、作用及其对网络传输的影响。根据用户提供的引用内容,我需要综合这些信息,并参考之前的对话内容,给出一个结构清晰的回答。 首先,用户给出的引用中有几个关键点: 1. 接收窗口(rwnd)是由接收方计算并通知发送方,用于流量控制。[^1] 2. 滑动窗口是接收方的流控机制,接收方根据处理能力缓冲区调整窗口大小。[^2][^3] 3. 拥塞窗口(cwnd)是发送方的流控机制,用于控制发送速率,避免网络拥塞。[^4] 用户之前的问题是关于调整MTU来解决TCP分段接收的问题,其中涉及到了MSSMTU关系以及协议栈配置。这可能与接收窗口大小调整有关联,比如更大的MTU可能影响每个报文段的大小,从而间接影响窗口的利用效率。 现在需要回答接收窗口的定义、作用及影响。需要明确以下几点: 定义:接收窗口是接收方通告给发送方的缓冲区可用空间,即接收方还能接收多少数据。发送方根据这个值调整发送的数据量,避免淹没接收方。 作用: 1. 流量控制,防止接收方被过多的数据压垮。 2. 允许发送方连续发送多个报文段,提高吞吐量,而不必每个报文都等待确认。 3. 动态调整,根据接收方的处理能力实时变化,适应不同的网络系统状况。 对网络传输的影响: 1. 窗口大小直接影响传输效率。窗口过小会导致发送方频繁等待确认,降低吞吐量;过大可能超出接收方处理能力,导致丢包或延迟。 2. 接收窗口与拥塞窗口共同作用,决定实际发送窗口大小(取两者较小值),从而综合控制网络流量,避免拥塞。 3. 高延迟网络下,较大的接收窗口可以更好地利用带宽,减少空闲时间,提升传输速度。 还需要注意引用中的内容是否有冲突或需要补充的地方。例如,引用[2]提到滑动窗口是接收方的机制,而引用[3]说明滑动窗口允许发送方持续发送数据。需要明确滑动窗口机制是双方共同参与的,接收方通过通告窗口大小来控制发送方的发送速率,而发送方根据这个窗口调整发送量。 另外,用户之前的问题涉及调整MTUMSS,可能需要提到接收窗口MSS关系,例如每个报文段的大小影响窗口能容纳的数据量。例如,接收窗口为rwnd字节,每个报文最多MSS字节,那么发送方一次最多发送rwnd/MSS个报文段。 还要考虑网络性能的方面,比如带宽时延积(BDP),即带宽乘以往返时间(RTT),接收窗口大小需要至少达到BDP才能充分利用带宽。如果窗口过小,即使网络带宽很高,实际吞吐量也会受限。 可能的遗漏点:接收窗口的动态调整机制,如TCP窗口缩放选项(Window Scaling),允许窗口大小超过65535字节,以适应高速网络。此外,零窗口问题,当接收方缓冲区满时,会通告窗口为0,发送方暂停发送,直到窗口更新。 需要结合用户提供的引用,特别是引用[1]中提到的接收窗口由接收方计算并通报,引用[3]中的动态调整流量控制作用,以及引用[4]中拥塞窗口与接收窗口的协同。 最后,生成相关问题时要围绕接收窗口流量控制、与拥塞控制的区别、性能优化等方面提问,确保问题与主题相关且能引导深入学习。</think>### TCP接收窗口详解 #### 一、定义与核心机制 **接收窗口(rwnd)** 是接收方通过TCP头部`Window Size`字段向发送方通告的**剩余缓冲区容量**,单为字节。其动态计算公式为: $$ rwnd = \text{接收缓冲区总大小} - \text{已缓存未处理数据量} $$ 例如若接收缓冲区为$64KB$,已缓存$32KB$未处理数据,则当前$rwnd=32KB$[^1]。 #### 二、核心作用解析 1. **流量控制** 发送方必须遵守$swnd = \min(rwnd, cwnd)$原则($swnd$为实际发送窗口,$cwnd$为拥塞窗口),通过限制发送速率避免接收方缓冲区溢出[^1][^4]。 2. **传输效率优化** 理想情况下,允许发送方持续发送$N$个报文段: $$ N = \left\lfloor \frac{rwnd}{MSS} \right\rfloor $$ 例如当$rwnd=64KB$且$MSS=1460B$时,可连续发送$\approx 44$个报文段[^3]。 3. **动态适应性** 窗口更新通过`ACK`报文传递,典型更新场景: - 应用层读取数据后释放缓冲区 - 网络抖动导致数据堆积时自动收缩窗口 #### 三、对网络性能的关键影响 | 性能指标 | 小窗口场景 | 大窗口场景 | |----------------|---------------------------|----------------------------| | 吞吐量 | 受限于窗口容量 | 可逼近带宽极限 | | 延迟敏感性 | RTT影响显著 | 对RTT容忍度提高 | | 带宽利用率 | 易出现空闲等待 | 更充分占用可用带宽 | | 丢包影响 | 单个丢包导致整体停滞 | 可通过后续ACK快速恢复 | **典型案例分析**: 在$1Gbps$带宽、$50ms$ RTT的网络中,带宽时延积(BDP)为: $$ BDP = 1Gbps \times 0.05s = 6.25MB $$ 若接收窗口小于$6.25MB$,则无法完全利用带宽,此时需启用**窗口缩放选项**(Window Scaling)突破传统$65535$字节限制[^2]。 #### 四、进阶配置建议 1. **操作系统级优化**(以Linux为例) ```bash # 调整接收缓冲区范围 sysctl -w net.ipv4.tcp_rmem="4096 87380 6291456" # 启用自动窗口调整 sysctl -w net.ipv4.tcp_window_scaling=1 ``` 2. **零窗口恢复机制** 当接收方发送$rwnd=0$通告后,发送方会启动**持续计时器**(Persist Timer),定期发送探测报文: ```c // 内核典型实现逻辑 if (rwnd == 0) { start_persist_timer(); send_window_probe(); } ``` #### 五、与拥塞控制的协同 接收窗口($rwnd$)与拥塞窗口($cwnd$)通过**Min函数控制**实现双重约束: $$ \text{实际发送量} = \min(rwnd, cwnd) \times MSS $$ 这种设计既防止接收方过载(流量控制),又避免网络拥塞(拥塞控制)。 ### 相关问题 1. 如何计算特定网络环境的最佳接收窗口大小? 2. TCP窗口缩放选项(Window Scaling)的实现原理是什么? 3. 接收窗口与拥塞窗口发生冲突时应如何优化? 4. 零窗口状态会导致哪些性能问题?有哪些解决方案? --- : 接收窗口由接收方计算并通告,用于流量控制 [^2]: 滑动窗口机制实现缓冲区动态管理 [^3]: 窗口机制提升传输效率的核心原理 : 拥塞窗口与接收窗口的协同控制机制
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值