核心功能
提供进程到进程的,可靠的,有效的传输服务
传输层的主要功能
- 屏蔽通信子网的多样性,为上层提供通用的接口
- 利用端口的不同,提供进程到进程的可靠服务
- 提供有连接的服务和无连接的服务
端口
传输层主要通过通信的端口来锁定到特定的进程上。
这张图很好的说明了,对于传输层的服务访问点,是通过端口来控制的。对于网络层的服务访问点,是通过主机(IP)来控制的。
端口的类型主要分为三个,包括:
- well-known:前0-1023
- Registered:前1024-49151
- Dynamic:前49152-65535
端口寻址
即,如何获得特定process的端口(TSAP)的问题。
对于比较特殊的服务,比如说邮箱服务器或者web服务器,都留有特定的端口来处理任务。
对于一般的任务而言,一般交由一个Portmapper来处理,根据client的服务请求将相应的TSAP地址返回给Client。
进程服务器:如果每个端口服务器都时时刻刻监听访问,未免有些浪费资源。因此启动一个进程服务器来进行监听的代理。为client的请求分配对应的端口。
差错控制
- ARQ机制,通过检查checksum字段进行错误检查并丢包
- 每个段都带有对应的序列号,只有收到对应序列号的ACK才正确接收
- 利用滑动窗口协议防止缓冲区溢出,并实现双工通信
和数据链路层的不同:传输层提供的是端到端的可靠服务,并且由于数据量大,必须开大窗口,同时重传不可忽略(误码概率相对更高)
缓冲区处理
对于缓冲区的处理,对于低带宽突发网络,无需预先分配固定缓冲区,而是动态在两端获取缓冲区。而高带宽流量,则需要接收方预先分配完整窗口缓冲区(以便计算最大传输速率)。
缓冲区类型
- 链式固定大小缓冲区
- 链式动态大小缓冲区
- 每个连接一个大循环缓冲区(用完了之后就会从头覆写)
流量控制
防止接收端收到数据过多无法处理而溢出
- 可变大小的发送窗口(A variable-sized sending
windows)
- 初始缓冲区协商(Initial buffer
negotiating):在通信开始时,发送方和接收方会协商确定初始的缓冲区大小,这直接影响到发送窗口的大小。
- 两个流量控制因素(Two flow control factor)
- 接收方可用的缓冲空间(Buffer space available in the receiver):
- 显式窗口指示(explicit window
indication):接收方会明确告知发送方当前可用的缓冲空间大小,即接收窗口的大小。这是流量控制的核心机制之一,确保发送方不会发送超过接收方处理能力的数据量。
- 子网容量(The capacity of the subnet):
- 发送方监控网络承载能力(sender monitor the network’s carrying
capacity):除了考虑接收方的缓冲空间外,发送方还需要监控整个子网的容量,以避免网络拥塞。这一部分属于拥塞控制(congestion
control)的范畴,旨在防止过多的数据涌入网络,导致性能下降或数据丢失。
复用网络层
如图所示,传输层支持在发送端将进程通过一个复用器,把进程的数据整合在一起,发往网络层。
在接收端,同样也有一个解复用器,可以将数据解析到对应的进程上。
拥塞控制
回想网络层,由于拥塞发生在路由器上,因此,网络层能检测到拥塞,但是网络层无法控制拥塞。而传输层所能做的,就是在接受到拥塞通知后,尽可能的减缓向网络层发包的速度,以此达到拥塞控制。
核心目的:
-
避免拥塞:这是最基本的目标,确保网络不会因为过多的数据流量而变得无法正常工作。
-
高效利用带宽:找到一种好的带宽分配方式,使得所有可用的带宽都能得到充分利用,提高网络效率。
-
公平性:在竞争传输实体之间保持公平,确保每个实体都能获得合理的资源份额。
-
快速收敛:能够迅速跟踪并适应流量变化,使网络状态尽快达到稳定状态。
功率
定义:
可以这样理解,在给定的时延中,所能承载的负载越大,说明这个网络的效率越高。
如下图所示,灰色部分的斜率较大,因此功率较小,即发生了拥塞。
网络的最好表现即功率最高的地方。
最大最小公平原则
该原则旨在高效分配带宽,使得每条链路的带宽尽可能的在满足最小需求的情况下,让低需求的信道获得更高带宽。以达到公平的目的。
换句话说,就是有点一碗水端平的意思。
我们来看看它的定义:一个信道上,在满足最小需求的前提下,各流尽量均分带宽;如果增加任何一个参与者(分量)的带宽,将导致其它的==具有相同或者更少带宽==的参与者(分量)的带宽下降,此时即满足了最大最小公平性。
这里很重要的一点是,允许在满足最小需求的情况下,让比它带宽大的参与者的带宽下降,也就是追求满足各信道最小需求的情况下的最平均。
我们举例子来说
先在脑子中把红色的线去掉。
对于R4-R5这条链路,是最拥挤的。因此我们要先对它进行分配。结果就是每个信道1/3的带宽。(这里是因为链路为1,所以可以这么想,但是实际上,如果不是所有链路都为1,那么从哪开始不一定,核心目的是找到每个路径的最限制它带宽)
然后就是对该路径上的所有信道进行1/3的分配。
最后,根据最大最小原则,对其余路径进行优化即可。
收敛
一个好的拥塞控制算法应该会很快的达到稳定的、理想的工作状态。
包括:
- 公平分配带宽(各数据流合理共享资源);
- 高效利用带宽(资源利用率接近100%);
- 动态适应网络变化(跟踪理想分配点的实时变化)。
发送方的速率控制
主要由拥塞控制和流量控制两者共同协作完成。
在互联网中主要就是以下三步
AIMD算法
我们知道,如果想要各个主机共享链路中的带宽,必须由发送方来控制,但是由于网络和其他主机的情况对当前主机是不可见的。因此,我们只能试探性的来探测网络容量的情况,这也就是我们AIMD算法的核心思想。试探!
可以简单的概括为:
可以发现,他就像是一个无赖一样,在你没发火(拥塞)的时候一点一点的得寸进尺,在你一发火的时候立刻退避三舍。
这个算法被证明可以达到所有主机的总体协作最优效率。
TCP协议中的AIMD
TCP不直接进行速率的调整,而是通过线性增加滑动窗口的大小,以及乘性减少滑动窗口的大小,间接地实现了发送速率的调整。
UDP协议
基本特性
- 提供无连接服务,通信前无需建立连接
- 不会拆分和合并应用层收到的数据,保持原样
- 提供不可靠的传输服务
- 无确认机制
- 无错误控制
- 无流量控制
- 无拥塞控制
- 不保证数据的可靠性
- 无确认机制
- 功能:
- 复用/解复用功能:提供共用网络层接口的功能
- 支持多种类型的数据报,包括广播,组播等数据报
- 复用/解复用功能:提供共用网络层接口的功能
一些使用UDP的协议
- DNS协议
- DHCP协议
- RIP协议
数据头格式
如图所示,一共使用8字节长的头部。其中,前16位用于标识发送方的Port,1732用于标识接收方的Port,3348用于标识总长度,最后16位用于纠错。
伪报头
可以理解为是,根据数据的信息,从IP头中提取出一部分信息,然后把IP的信息也纳入checksum的计算范围,提供更加强大的差错检验功能。
实际传输的过程中,不会传输伪报头。接收端在接收到数据之后,会根据数据重新创建一个对应的伪报头,然后检查其checksum。
TCP协议
特点
- 设计目的:提供一个面向连接的、可靠的端到端字节流
- 面向连接的特性:
- 全双工通信
- 端到端通信
- 套接字:每个TCP链接可以由一对套接字唯一标识。每个套接字包含其IP地址和对应的端口。TCP链接由源套接字和目标套接字确定。
- 知名端口:低于1024的端口遵循RFC1700标准,为标准服务预留。如下表所示
- 全双工通信
- 可靠服务的特性:
- 使用ARQ机制(包括累计确认,超时重传,Checksum,滑动窗口,序列号,计时器)
- 拥塞控制:共享网络资源
- 面向字节流的消息:消息边界无法保存,TCP具有分片功能,不能保留消息边界,分片长度和数量由TCP协议决定,和上层数据无关。TCP保证交给上层的数据按序且正确。
如图所示,逻辑上体现为字节流,实际上由报文段封装传输,通过分配适应MTU
- 使用ARQ机制(包括累计确认,超时重传,Checksum,滑动窗口,序列号,计时器)
- 面向连接的特性:
TCP数据头
1. 源端口 (Source Port)
- 作用: 标识发送该 TCP
报文段的应用程序或服务的端口号。
- 长度: 16 位 (2 字节)。
- 解释:
当接收方需要回复时,会使用这个端口号作为目的端口(在回复报文中)。它告诉对方“我来自哪个门”。取值范围是
0-65535,其中 0-1023 是众所周知的端口,通常由系统级服务使用。
2. 目的端口 (Destination Port)
- 作用: 标识接收该 TCP
报文段的应用程序或服务的端口号。
- 长度: 16 位 (2 字节)。
- 解释:
指定报文应该递交给接收方主机上的哪个具体应用程序或服务。它告诉对方“我要去哪个门”。例如,HTTP
服务器通常监听 80 端口,邮件服务器 SMTP 监听 25 端口。
3. 序号 (Sequence Number)
- 作用: 用于保证数据的顺序交付和实现可靠性。
- 长度: 32 位 (4 字节)。
- 解释:
-
在建立连接的初始 SYN
报文中,这是客户端选择的随机初始序号
(ISN
)。
-
在后续的数据报文中,这是本报文段所携带数据的第一个字节的编号。
-
这个序号是相对于字节流的绝对编号。接收方依靠这个字段来识别数据是否按顺序到达,并对乱序到达的数据进行重组。
- 关键点: TCP
把要发送的数据视为一个连续的字节流,并对每个字节编号。
4. 确认号 (Acknowledge Number)
- 作用:
用于确认对方成功接收到的数据(期望接收的下一个字节序号)。
- 长度: 32 位 (4 字节)。
- 解释:
- 仅在 ACK
标志位被置为 1 时有效。
-
表示发送该报文的这一方期望收到的下一个字节的序号。
-
例如,如果确认号是 1001
,意味着对方已经成功地、按顺序收到了序号 1000
及之前的所有字节(流结束标记不算实际数据)。
-
它是对已经接收到的最后一个字节的下一个字节的确认。
5. 首部长度 / 数据偏移 (Header Length / Data
Offset)
- 作用: 指示 TCP 报头本身的长度(以 4 字节的
字 为单位)。
- 长度: 4 位。
- 解释:
- 该字段的值乘以 4 就得到 TCP 报头的总字节数。
- 标准首部(无 Options
)长度是 20 字节(5
* 4 = 20)。
- Options
字段的存在会增加 TCP 报头长度。这个字段用来确定
TCP 数据载荷(Data
)部分从哪里开始。
6. 保留位 (Resv)
- 作用: 预留供将来使用。
- 长度: 6 位。
- 解释: 目前必须全部置为 0。
7. 标志位 (Flags / Control Bits)
- 作用: 控制 TCP 连接的状态和数据的发送行为。
- 长度: 6 位 (各占 1 位)。
- 解释: 每个标志位都是一个开关(1 表示开启/有效,0
表示关闭/无效):
- URG (Urgent):
置位时,表示报文段包含紧急数据。此时 Urgent Pointer
字段有效,指示紧急数据在数据部分中的结束位置(相对于序号的偏移)。
- ACK (Acknowledge): 最常用的标志位!
置位时,表示 Acknowledge Number
字段有效。连接建立后(过了
SYN 阶段),通常该位总是置 1,表示正在携带一个有效的确认号。
- PSH (Push):
置位时,指示接收方应立即将数据交付给上层应用,而不是缓存起来等待更多数据。这类似于发送方在说:“推一下,别等了!”
- RST (Reset): 强制重置连接!
置位时,表示发生了严重错误(如请求不存在的端口、连接中断),需要立即终止连接。接收方收到
RST 后会立即放弃该连接。
- SYN (Synchronize):
请求建立连接的标志位。在建立连接的初始握手阶段置位(第一次握手从客户端发往服务器,第二次握手从服务器发往客户端)。携带 SYN
的报文会初始化序列号。
- FIN (Finish):
请求关闭连接的标志位。发送方数据发送完毕,想优雅地终止连接时会置位。对方需要确认。
8. 窗口大小 (Window Size)
- 作用:
用于流量控制。接收方通告发送方其当前可用的接收缓冲区空间大小(以字节为单位)。
- 长度: 16 位 (2 字节)。
- 解释:
-
发送方每次传输的数据量不能超过接收方通告的这个窗口大小。
-
这是一个动态值,在连接过程中会不断变化(通过带有 ACK
的报文发送)。
- 目的是防止发送方发送的数据过快或过多而导致接收方缓冲区溢出。
9. 校验和 (Checksum)
- 作用: 用于检测报文在传输过程中(首部 +
数据)是否有损坏或错误。
- 长度: 16 位 (2 字节)。
- 解释:
发送方计算该值并填入。接收方重新计算校验和:如果与收到的值不匹配,则丢弃该报文(可能触发重传)。覆盖范围包括
TCP 伪首部(包含源/目的 IP 地址和协议号等信息) + TCP 报头 + TCP
数据。它提供端到端的错误检查机制。
10. 紧急指针 (Urgent Pointer)
- 作用: 仅当 URG
标志位置为 1
时有效。 指示紧急数据在数据部分的结束位置。
- 长度: 16 位 (2 字节)。
- 解释:
这是一个偏移量,相对于当前报文段的 Sequence Number
。比如,如果 URG=1
,Seq=1000
,Urgent Pointer=50
,那么紧急数据的范围是从 Seq=1000
到 Seq=1050
(1000+50)。接收方处理这种数据通常优先于普通数据(如 Ctrl+C
中断信号)。
11. 选项 (Options)
- 作用: 提供一些额外的功能或配置。
- 长度: 可变长度(0 到 40 字节,总是 32
位的倍数)。
- 解释:
- 某些选项是连接建立(SYN 阶段)时必须协商的。
- 常见选项:
- 最大段大小 (Maximum Segment Size - MSS):
在连接建立时协商,表示 接收方 希望接收的单个 TCP
报文段的最大数据部分长度(不包括 TCP/IP
首部)。目的是适配双方网络的 MTU,减少分片。
- 窗口缩放因子 (Window Scale Factor): 解决 16
位 Window Size
字段最大值(65535
字节)在高速或长延时网络中不够用的问题。通过左移操作(乘以缩放因子)来扩展实际的接收窗口大小。
- 时间戳 (Timestamp): 用于更精确地计算往返时间
(RTT
),这对于 TCP
的拥塞控制算法很重要;也有助于解决序号回绕 (PAWS
)
问题。
- 选择性确认 (Selective Acknowledgment - SACK):
允许接收方告知发送方已经成功接收到的非连续数据块,使得发送方在数据丢失时能够更高效地进行重传(只重传丢失的块)。
12. 填充 (Padding)
- 作用: 确保 TCP 报头的结束位置是 32 位(4
字节)的边界对齐。
- 解释:
- 由于 Options
字段长度可变,可能不是 4 字节的倍数。
- 当 Options
的存在使得报头总长度不是 4
字节的整数倍时,会在 Options
字段后面添加足够的 0
作为填充(即
padding 字节全为
0),使整个报头长度符合 Header Length
字段指示的字数。
- 它本身不是一个独立的数据字段,只是为了对齐需要而加入的空字节。
连接建立过程
如图所示,流程如下:
1) 客户端发送含有SYN的数据包,并附带随机生成的初始序列号。
2)
服务端收到SYN数据,返回ACK和SYN都有的一个数据包,并附带随机生成的初始序列
3) 客户端返回ACK,表示连接建立
4)
注意,纯ACK包不占用序列号,这意味着下一个发送的包的SEQ还是x+1。以下为WireShark抓包结果,用以说明ACK不占用序列号。点开4之后看到
证明确实不占用序列号
为什么一定要三次握手?
这个问题不如用:“两次握手会发生什么问题?”来替代。
想象一下通信过程,对于服务端,假如回复的ACK丢包,那么,此时无法判定接收方是否成功建立连接,也无法知道接收方是没有东西传过来还是没有成功建立连接。因此,就必须划分出一部分资源来监听接收方的请求。此时,如果是没有成功建立连接的情况,就造成了极大的资源浪费。
因此,为了避免这种资源浪费,我们选择三次握手,只要发送方不确认链接建立,就不给它分配资源,这样,就把==判定有没有成功建立连接的风险抛回给了发送方==。但是对于发送方而言,它是不会浪费资源的,他只需要再试一次,然后得到未建立链接的结果,然后重新建立连接就行了,这个过程是不会浪费资源的,最多也就是一点发送方的资源,对服务器没有影响。这就确保了服务器的通信的流畅。
数据传输过程
重点是掌握SEQ和ACK的取值
ACK所指向的是对方下一个期望的字节的起始序列号
SEQ则是当前字节的数据的起始序列号
连接释放过程
1) 首先由客户端发出含有FIN请求的包,申请连接中止
2)
服务端回复一个ACK包,但是不回复FIN,此时代表服务端还有数据需要发送给客户端
3)
等到服务器的所有内容都发送完毕,服务器发送含有FIN的包,请求终止连接
4) 客户端回复一个ACK,代表连接成功中止
必须四次挥手的理由和三次握手相似,这里不做过多解释
特别的,如果发送方没有多余的数据要送,那么三次挥手即可
流量控制:滑动窗口
特点:
- 动态管理发送窗口大小:根据ACK报文中的Window
Size字段通知发送方自己还剩多少buffer。
- 缓存已满:发送Window Size=0的ACK,通知发送方暂停发送数据,但是Urgent
data可以被发送,发送方可以定期发送一个一字节的数据段用于探测接收方是否更新了窗口大小,防止通信死锁。
- 发送方并不立刻传送每一个从应用层到达的包。我们使用nagle’s
algorithm来解决这个问题。只发送第一部分用于建立连接,然后,发送方等待直到满足以下条件之一才进行传输:
- 收到上一个段的ACK
- 数据缓冲区中的内容已经过半
-
与之相对的,接收方也并不立刻回复ACK,而是需要等待数据被接受一部分之后,缓冲区有足够大的空间之后才回复ACK,这里我们使用Clark’s
Solution,直到接收方满足以下两个条件之一才返回ACK:
- 接收方的缓冲区的空闲部分可以处理MSS(最大段长)
- 接收方一半以上的缓冲区是空闲的
差错控制:ARQ
- 发现错误:Checksum
- 核心机制:超时重传,设置RTO(Retransmission
Time-Out)timer,设置ACK用于确认某一段被收到
- 正常运行流程:
- 若发生段丢失:
此时,回复的ACK仍然是之前期望的ACK,基于此,发送方就会重传被期望的那部分数据,然后基于累积重传的机制,选择下一个要发送的数据段
- 快速重传机制:
如果三个及以上重复的ACK被收到,那么发送方将立即重传该包,而不必等待RTO
关于TCP的TIMER的管理
Timer的分类:
- 重传Timer:用于超时重传机制
- Persistence
Timer:用于防止0窗口死锁。当接收方的窗口大小字段被设为0的时候使用,用于询问接收方的窗口大小情况。到期后向接收方发送询问,接收方发送其窗口大小。
- Keep-alive
Timer:用于防止半开放连接。当另一方很久没有发消息的时候使用,用于检查另一方是否还保持着连接。允许接收方据此断开连接
- Time-waited
Timer:一般是两倍的最大数据包的生存时间,用于确保当连接断开的时候,所有的数据包都已经被接受,没有在路途中的数据包。
重传Timer的时间设置
TCP协议的重传时间设置要远难于数据链路层。因为RTT时间的分布在传输层更加的分散,没有数据链路层的集中。这是由于底层网络的异构性导致的。基于此,我们需要选择一个合适的时间,来作为重传的Timer。
为此,我们可以使用一个动态的算法,来动态地设置重传的Timer。
Jacobson算法:动态评估RTT
- 不计算RTT,而是使用更平滑的加权平均过的SRTT
-
- 由于丢包情况等非正常包,RTT的采样不会准确,因此引入Karn’s
algorithm:
- 每次连续重传都要将RTO乘以2,可以理解为是指数退避
- 对于丢包等情况的RTT,不纳入采样
TCP四大核心算法总结
算法 (Algorithm) | 旨在解决的问题 (Problem Solved) | 核心解决方案 (Core Solution) |
---|---|---|
Nagle算法 | 防止发送方因应用层产生少量数据而频繁发送”小数据包”(tiny packets),这会增加网络头部开销,降低传输效率。 | 发送方在发送第一个小数据段后,会等待,直到收到对该数据段的确认(ACK)或者累积了足够多(如一个最大段长MSS)的数据后,才发送下一个数据段。 |
Clark算法 | 防止接收方通告一个非常小的可用窗口(例如,仅能接收几个字节),从而诱使发送方发送小数据包,造成网络效率低下(糊涂窗口综合症的接收方问题)。 | 接收方推迟发送窗口更新的ACK,直到其缓冲区有足够的可用空间(例如,能容纳一个最大段长MSS的数据,或者其缓冲区一半以上为空闲状态)。 |
Jacobson算法 | TCP的往返时间(RTT)因底层网络的异构性而剧烈变化,导致难以设置一个固定的或简单的超时重传定时器(RTO),容易造成过早或过晚的重传。 | 使用动态的加权移动平均算法来估算一个更平滑的往返时间(SRTT),并结合RTT的方差来动态地计算RTO,使其能更好地适应网络延迟的实时变化。 |
Karn算法 | 当数据包被重传时,收到的ACK是对应原始包还是重传包存在“重传模糊性”。如果用这个不准确的RTT样本来更新RTO的计算,会污染结果。 | 1. 忽略模糊样本:不将任何重传过的数据包的RTT样本纳入SRTT的计算中。 2. 超时退避:每当发生一次超时重传,就将RTO的值加倍(指数退避),以应对可能的网络拥塞。 |
拥塞控制
路由器
- 主要负责检测到拥塞
发送方
- 在接收到拥塞通知之后,需要降低发送速率,来防止拥塞
- 利用AIMD算法维护
cwnd
拥塞发送窗口
- 流量控制滑动窗口算法维护
rwnd
流量窗口
- 为了兼顾网络拥塞和流量控制,最终实际的发送窗口取
min(cwnd,rwnd)
- 将丢包视为网络拥塞的标志
- 动态调整发送速率,在拥塞的时候降低发送速率,在畅通的时候(正常收到ACK)增加发送速率
总过程
- 慢启动:首先设置
cwnd=1
,然后每次正确收到ACK就翻倍增长
- 设置阈值
ssthresh
,当窗口达到这个大小之后,就转为加型增长,开始调用AIMD算法
- 若丢包/收到拥塞通知,那么调整发送窗口回到1,认为网络拥塞了。
- 恢复过程:
TCP Tahoe
核心思想: 探测网络可用带宽,并在检测到拥塞(丢包)时采取非常保守的措施。
主要机制:
- 慢启动: 连接开始时或检测到拥塞后,发送方从一个很小的拥塞窗口开始。每收到一个
ACK,窗口增加 1 个
MSS。这导致窗口大小呈指数增长,目的是快速探测可用带宽。
- 拥塞避免: 当拥塞窗口达到慢启动阈值后,进入拥塞避免阶段。此时窗口的增长变为线性增长(通常每个
RTT 增加 1 个 MSS),目的是更谨慎地逼近网络容量。
- 拥塞检测与响应:
超时重传: 如果发生超时,Tahoe 认为发生了严重拥塞。
重复 ACK: 收到3 个重复 ACK,Tahoe 认为发生了轻度丢包(可能是单个包丢失)。
- 拥塞响应:
- 无论哪种丢包信号(超时或 3 个重复 ACK):
- 将慢启动阈值设置为当前拥塞窗口的一半。
- 将拥塞窗口重置为 1 个 MSS。
- 重新开始慢启动过程。
- 将慢启动阈值设置为当前拥塞窗口的一半。
- 无论哪种丢包信号(超时或 3 个重复 ACK):
- 慢启动: 连接开始时或检测到拥塞后,发送方从一个很小的拥塞窗口开始。每收到一个
ACK,窗口增加 1 个
MSS。这导致窗口大小呈指数增长,目的是快速探测可用带宽。
特点:
- 保守: 对任何丢包(即使是单个包的快速重传触发的丢包)都反应过度,直接将
cwnd 降到
1。这导致在丢包后,吞吐量会急剧下降,需要重新经历慢启动的指数增长过程,恢复速度较慢。
- 锯齿状: 窗口大小变化呈现明显的“锯齿”模式:快速上升到某个点(发生丢包)->
窗口骤降到 1 -> 慢启动 -> 拥塞避免 -> 再次快速上升…。
- 效率问题: 在发生单个包丢失时,将窗口重置为 1 过于激进,会导致链路利用率在恢复期间显著降低。
- 保守: 对任何丢包(即使是单个包的快速重传触发的丢包)都反应过度,直接将
cwnd 降到
1。这导致在丢包后,吞吐量会急剧下降,需要重新经历慢启动的指数增长过程,恢复速度较慢。
TCP Reno
- 核心思想: 在 Tahoe
的基础上进行改进,主要针对单个包丢失的情况。Reno
区分了超时丢包和快速重传丢包,并引入了快速恢复机制来处理后者,避免在单个包丢失时不必要的回退到慢启动。
- 主要机制:
- 慢启动: 与 Tahoe 相同。
- 拥塞避免: 与 Tahoe 相同。
- 拥塞检测:
- 超时重传: 与 Tahoe 相同,认为是严重拥塞。
- 重复 ACK: 收到 3 个重复
ACK,认为是单个包丢失。
- 超时重传: 与 Tahoe 相同,认为是严重拥塞。
- 拥塞响应:
- 超时重传: 响应方式与 Tahoe
完全相同:
- 设置
ssthresh = cwnd / 2
- 设置
cwnd = 1 MSS
- 进入慢启动。
- 设置
- 3 个重复 ACK (触发快速重传和快速恢复):
- 设置
ssthresh = cwnd / 2
。
- 快速重传: 立即重传被重复 ACK
指明的那个丢失的数据包(而不等待超时)。
- 快速恢复:
- 设置
cwnd = ssthresh + 3 MSS
。(加 3 是因为收到了 3 个重复 ACK,表明有 3 个数据包已经离开网络)。
- 对于后续收到的每一个额外的重复
ACK,将
cwnd
增加 1 MSS。这相当于“注入”新包填补网络中因重传包离开而空出的位置。
- 当收到一个新的
ACK(确认了之前未确认的序列号,包括重传的那个包)时:
- 设置
cwnd = ssthresh
。(退出快速恢复状态)
- 进入拥塞避免阶段(线性增长)。
- 设置
- 设置
- 设置
- 超时重传: 响应方式与 Tahoe
完全相同:
- 慢启动: 与 Tahoe 相同。
- 特点:
- 区分拥塞程度: 超时代表严重拥塞,3 个重复 ACK
代表轻度拥塞(单个丢包)。
- 快速恢复: 这是 Reno 相对于 Tahoe
最关键的改进。在检测到单个包丢失时:
- 避免了将
cwnd
重置为 1。
- 在重传丢失包期间,利用收到的重复 ACK
继续缓慢地增加
cwnd
,保持数据流。
- 重传成功后,直接从
ssthresh
进入拥塞避免阶段,而不是慢启动。
- 避免了将
- 性能提升: 在发生单个包丢失时,Reno
能维持更高的吞吐量,连接恢复速度更快,网络利用率更高。
- 锯齿状改善: 窗口变化在单个丢包时不再是断崖式下跌到
1,而是降到一个较高点(
ssthresh
)后进入线性增长,锯齿的“谷底”变高了。
- 多个丢包问题: 如果在一个窗口内丢失了多个包,快速恢复机制可能无法收到足够多的重复 ACK 来维持快速恢复状态(可能触发超时),导致最终仍要回退到慢启动。这是 Reno 的一个主要缺点,后续的 NewReno 和 SACK 等算法对此进行了改进。
- 区分拥塞程度: 超时代表严重拥塞,3 个重复 ACK
代表轻度拥塞(单个丢包)。
关键区别总结表
特性 | TCP Tahoe | TCP Reno |
---|---|---|
主要改进 | 基础算法 (慢启动, 拥塞避免, 快速重传) | 在 Tahoe 基础上增加快速恢复 |
对 3 个重复 ACK 的反应 | 重置 ssthresh = cwnd/2 重置 cwnd = 1
进入慢启动 |
重置 ssthresh = cwnd/2
快速重传丢失包 设置 cwnd = ssthresh + 3
(+3是重传三个ACK的包)进入快速恢复 (收到新ACK后进入拥塞避免) |
对超时的反应 | 重置 ssthresh = cwnd/2 重置 cwnd = 1
进入慢启动 |
==与 Tahoe 相同== |
核心思想 | 任何丢包都代表严重拥塞,必须完全回退 | 区分拥塞程度:超时=严重,重复ACK=轻度(单个包) |
单个丢包性能 | 差:窗口骤降至 1,恢复慢 | 好:窗口降至 ssthresh ,恢复快,保持较高吞吐量 |
窗口变化 | 明显的“锯齿” (谷底为 1) | 改善的“锯齿” (谷底为 ssthresh ) |
多个丢包问题 | 存在 | 存在 (可能导致快速恢复失败并退化为超时处 |
如果您喜欢我的文章,可以考虑打赏以支持我继续创作.