简单聊一下 TCP 协议

发布于:2025-07-09 ⋅ 阅读:(21) ⋅ 点赞:(0)

大部分的应用层协议,比如 HTTP,FTP,DNS 底层都基于或者依赖TCP协议,虽然在网站开发中,我们很少会和传输层协议直接打交道,但是还是需要了解其原理,这里简单做一下笔记和总结。

TCP全称传输层控制协议 ( Transmission Control Protocol )目的在通信双方建立可靠的链接。

与其相对的是传输层中常用的另一个 UDP协议 即 用户数据报协议 (User Datagram Protocol ) 

相对于TCP,UDP面向不可靠,无连接,将可靠传输,流量控制等直接交给上层,更高效率的同时

也导致了数据的不可靠性。

我们知道,网络通信是不可靠的,线路中可能会存在拥堵,可能会丢包,通信双方发送接收数据的能力也可能不一致,而TCP 协议主要解决这些问题,具体包括:

  1. 提供可靠传输,保证通讯双方得到的数据是正确的
  2. 流量控制,协商通信双方数据的首发速度,保证接收方有能力处理发送方发来的数据
  3. 拥塞控制,保证通讯链路的通畅,避免链路拥堵

下面我们就具体来看一下TCP的具体工作原理。

流式传输

你可以把TCP协议当成是一条自来水管,从一方灌入自来水,另外一方接收,不用考虑之间会不会漏水,会不会有污染 等等,TCP会帮你保障这些。

你需要做的就是和另外一方商量好接收数据的长度,比如发送方告诉你需要接收1000字节的数据,你就在另外一方接收数据并且记录,当接收完1000个字节,即可完成接收。

TCP段 头部结构

TCP会对发送的数据进行切分,每个切分单元被称为 段 Segment 。以段为单位的信息会像流水一样被发送给对端。

由于网络环境复杂,端的到达可能是乱序的,可能丢失,这就需要对端检验端信息的正确性。

TCP会对每个段 增加一个约20字节的头部,这个头部携带着段相关的信息,其的结构如下: 

 正常情况下,tcp段头部的长度为 20字节,但是其长度可以扩展,最长可以扩展到 60字节。

未扩展的TCP段头部为 4字节 (32bits)一行,包含4行

第一行为发送端和接受端的端口号,长度分别为 2字节,16bits,表示范围是 [0,65535] 这也是端口号的可用范围,TCP通过 源目的 IP 源目的端口 这个四元组来确定一个连接,而IP信息保存在上层的网络头部中。

第二行为Seq序号,也就是确认序号,长度为4字节 32bits

第三行为Ack应答序号,长度和Seq相同

第四行前4个字节为数据偏移,其表示范围是 0 - 15 代表当前段的内容从当前段的哪个位置开始。也就代表首部长度。 其计算方式为 段数据偏移 * 4字节 (也就是一行)最大可以表示 60字节的偏移长度,也就对应了我们上面说的,段首部可最大扩展到 60字节

后面6字节为保留位,目前没用

后面的6位为标志位,常用的比如

  • ACK, 当前位为1的时候,确认号生效,表示当前段包含响应号
  • SYN 用来创建TCP连接
  • FIN 用来断开TCP连接
  • PSH 表示数据需要立刻推送给应用层 不缓存
  • URG  配合紧急指针启用 表示数据中存在紧急数据,告诉接收端优先处理。
  • RST: 立即强制断开连接,用于异常中断或非法连接。

后面2字节16bits为窗口大小,表示接受端能接受的窗口尺寸,最大为 65535 这个下面详细讲 

后面就是2字节的checksum和2字节的紧急指针

5行20字节之后,就是扩展内容Option,具体由数据偏移确定,包含MSS SACK内容 等等

面向连接

TCP和UDP不同,TCP面向连接,需要在通讯开始之前,确定接收方是存在并且可以接受和发送数据的。这就需要发送端和接受端在传输数据之前协商出一条逻辑上的链路出来。

注意,这个链路不是物理的链路,是逻辑上的链路,具体来说是发送接受端各自维护一套双方的信息。

网络中,一条TCP连接通常由 四元组 确定 其包含

[ 发送方IP , 发送方端口,接收方IP,接收方端口]

如下: 即为多条 TCP链路

同时,通讯双方还需要交换 比如 发送序号,窗口大小,连接状态等信息,这个过程通常由三次握手完成。

三次握手

这一部分可以说是面试中老生常谈的问题了,其过程如下:
通讯双方都有各自的状态,三次握手就是将双方的状态从 Close 变成 Established的过程

为什么需要三次? 本质目的是需要通讯双方都要确定各自有 发送 和 接收 数据的能力

第一次,发送端发送 SYNC端,其段头部的SYNC标志为1表示发送端想建立连接, 并且携带seq为x值( 不一定从0开始 )

发送成功之后,发送端的状态就从Close -> SYN_SENT 表示建立连接的请求已经发送

第二次,接收端收到SYNC段之后,把状态从LISTEN改成SYN_RCVD 表示建立连接的请求已经接收到。 此时,接受端就能确认自己能接受数据,有接收数据的能力。

接收端返回一个应答段,其中ACK标志为1 SYN标志为1  表示发送端SYN已经收到,接受端也想和发送端建立连接,并且返回ack为x+1 seq = y 表示想接收的下一个段,编号为x+1 并且当前接受端的发送序号为y。 由于TCP是全双工的,所以要求双方都持有对方的发送序号。

发送端收到之后,就能确认自己有发送 和 接收数据的能力,并把自己的状态改成ESTABLISHED

表示发送端已经做好发送准备 

第三次,发送端还需要让接受端知道发送端接收到了ACK,让其确认自己有发送数据的能力,所以发送一个ACK = 1 ack=y+1 作为应答

接受端接收到之后,确认自己有发送数据能力,把状态改成ESTABLISHED,链路建立完成。

链接建立完成后,双方都持有对方的发送序号,就可以开始发送数据了。

如何记忆? 三次握手本质目的是让通讯双方确认自己有 发送 接收 数据的能力,按照这个去记忆。

四次挥手

数据发送结束后,TCP连接需要被安全的关闭,发送双方需要确保所有需要发送的数据都发送完成

这个过程需要四次挥手来完成协商。 如下:

不论是发送方还是接收方,都可以主动断开连接,不同于三次握手,断开连接发起的一方称为 主动断开端,另外一端为被动断开端。

第一次挥手,主动断开端发送FIN段,其中ACK = 1 FIN = 1  seq = x ( 主动 断开端序号 )ack = y (被断开端序号) 并且切换到 FIN_WAIT1 状态,等待被断开端回应

第二次,被断开端接收到FIN请求之后,回应对应的ACK = x + 1 表示知道需要断开连接了,但是不能立刻断开,因为被断开端还有可能有数据没发送完,需要发送完之后才能断开。发送完ACK后,被断开端进入 CLOSE_WAIT状态,发送剩余信息

主动断开端收到ACK 表示对端已经知道要断开了,就进入 FIN_WAIT2 阶段,次阶段的主动断开端不能发送消息,只能接收消息并且回应

第三次,被断开端发送完剩余数据后,此时的seq为 y+3 发送 FIN = 1 ACK = 1 ack = x+1 seq = y+3 表示被断开端也想断开连接了。发送之后进入 LAST_ACK状态,表示等待接受主动断开端发送的最后一个对FIN请求的确认

第四次,主动断开端收到对端的FIN请求后,返回应答 ACK = 1 ack = y+4 并且进入TIME_WAIT状态,被断开端收到ACK之后进入CLOSED状态

主动断开端需要等待 2*MSL时间,之后进入CLOSED状态

MSL (Maximum Segment Lifetime) 最大段存活时间 

TCP 报文段(Segment) 在网络中存活的最长时间、MSL是理论的约定值,表示一个数据包从发出到被丢弃,这个最大的时间是MSL,等待MSL之后,这个数据包一定已经被丢弃了!

注意,网络设备依靠TTL丢弃数据包,不看时间戳和MSL,MSL只是约定的一个时间,一般比较大,大于 RTT RTO等

为什么需要等待 2MSL? 

我们知道 TCP连接是可以被复用的,这就需要保证每次复用之前,上一次连接发出的数据段在网络中已经都不存在了,如果还存在就会干扰下一次的复用。

所以,主动发起断开端需要等待2MSL的时间,这段时间内无法复用当前连接,以保证2次连接之间不会干扰。 

为什么是2MSL? 不是 MSL?
1. 主动断开端发送的最后的ACK需要等待 1MSL才能在网络中消失

2. 被断开可能没接收到最后的ACK,需要确保其进入CLOSED状态,如果被断开端迟迟没收到最后的ACK,就会重新发送FIN请求,我们假设当最后的ACK发送到对端之前突然丢失了,这个时间最迟是1MSL,那么对端最迟发出再次FIN的时间也是1MSL,这个FIN再次发送到主动断开端也需要1MSL,所以一共等待 2MSL是最保险的做法。

由于主动断开端需要等待2MSL才能复用连接,所以一般不要让服务器作为主动断开端,会占用服务器资源。

分段传输

上面说了,TCP协议在传输数据时,会尽可能把数据拆分或者组合成 一个一个的段 Segment 进行发送,分段的原因有以下几点

  1. 主要原因是,数据链路层在物理层面上规定了网络链路中的最大传送单元 MTU (Maximum Transmission Unit,最大传输单元)所有上层协议传递下来的数据包都不能超过这个长度。
  2. 分段传输有更高的容错性,一个段的数据出错可以只传送这一个段,不用全部数据重传
  3. 数据分段传输有利于接收端接收数据,接受段不必一次性处理大量数据,同时链路中节点的压力也会变小。有利于流量控制和拥塞控制

正常情况下,最大传输单元MTU为 1500字节,IP层协议头占20字节,留给TCP协议的长度大概为1480字节。 

如果一个TCP段的长度超出了 1480字节,下层的IP协议会得Segement进行拆包,我们不希望Segment被IP层再次拆分,这样会增加数据包的丢失风险,一般情况下我们会用 MSS来限制段的长度。

MSS 为 Maximum Segment Size 即段最大长度,通常为 MTU - 网络层头部长度 - TCP段头部长度 = 1500 - 20 -20 -1460字节。

TCP协议会将上层协议传递下来的内容切分成很多段,(这些段的最大长度为 MSS)并且对这些段按顺序标号并发送给接受端,接受端在接收到这些段并且检查顺序无误后,即可发送给上层协议。

可靠传输

我们在使用应用层协议 如 HTTP 发送请求时,似乎从来都没关心过我发送的数据到底会不会在传递的过程中出错,会不会有链路上的干扰导致 0 1 数据错乱,会不会因此数据解析失败乱码?

如果你做过大文件传输,当我们把分片之后的数据发送到服务器时,有没有考虑过要不要给这个分块做一下数据校验? 比如同时携带一个 hash过去,服务端收到数据再对其进行一次hash进行比对

其实这些都是不用的,网络协议栈分层的一个主要原因就是,分工独立,每一层只做自己的事情,上层协议直接使用下层协议提供的数据,不用考虑下次协议如何实现,是否正确实现等等。

HTTP作为TCP协议的上层协议,默认下层TCP传递来的数据就是正确的,不需考虑数据的校验,切分和组合。

TCP如何实现可靠传输呢

SEQ序列号&ACK确认号

TCP会对每个待发送的字节编号,发送编号一般用Seq表示。比如当前从Seq = 0开始发送,发送长度为一个MSS长度 1460字节

接受端也需要维护这个Seq信息,当一个MSS的数据发送完之后,发送端会等待接受端的确认,接受端接收到这1460字节的数据之后,会将自己维护的发送端Seq调整到 1459,并且返回一个确认报文,通常用ack表示。

ack即Acknowledge,表示下一次发送期待接收的seq序号,这里的ack = seq+1 即 1460 表示接受端希望下次接收第1460号字节。发送完ack之后,接受端就可以把0-1459字节的数据提交给上层协议了。

发送端收到接受端的ack之后,就知道自己发送的 0 -1459号数据都被正确接受了,就可以调整自己的seq到1460的位置并且继续发送。如下:

如果这个过程中,0-1459字节作为一个段整体传输,如果这个段在网络传输中丢失,或者部分数据传输错误,接受端检验发现错误之后,会直接丢弃这个段,发送端会对每个段的发送设置一个计时器,当计时器超时还没收到接受端的ack响应,就会重新发送这个段。

如果接受端成功接受了 0-1459这个段,也返回了ack应答,但是ack在网络传输中丢失,这会导致发送端重新发送这个段,接受端在接收之后发现段重复了,就会再次响应Ack给发送端。

早期的TCP设计中,段的接收必须是按照seq顺序来的,如果中间某个段丢失,后面的段也无法接受,必须等待发送端重新传。 通过这种方式,就能保证接受端能正确的且按顺序的接收数据。

checkSum 校验和

接受端除了要按照顺序接收段数据,还需要保证段内容的正确性,每个段会在头部的位置携带2字节的校验和字段,这个字段通过段内容生成,接受端接收到后,需要对段内容重新计算校验和,比对无误之后才能确认接收,否则就抛弃当前段。

总结 : 

TCP 用序列号+确认号保证数据有序且完整,用重传机制保证丢包数据重新发送,利用流量控制拥塞控制调节发送速度防止丢包,结合校验和保障数据正确性,确保了可靠传输。

流量控制&高效传输

流量控制通常会和拥塞控制混淆,其实这是两个概念。

前者流量控制,解决的是通讯双方收发速度的协商和控制,也就是说当接收方接收不过来时,发送方会适当降低发送速率。

后者流量控制,解决的是连接通讯双方之间的链路上阻塞的问题,当检测到链路拥塞的时候,所有使用TCP协议的发送方都会适当放缓发送速率,以保障整个链路的通畅。

重传时间 RTO

说流量控制之前,我们需要先区分两个概念 RTT RTO

RTT (Round Trip Time) 往返时延,指的是从发送方发出数据到接收到接收方的确认(ACK)所经历的总时间。也就是数据一个来回所消耗的时间,RTT的大小通常不确定,会随着网络的情况而变化。

RTO(Retransmission Timeout,重传超时) 是 TCP 协议中的一个关键机制,用于确定当数据包丢失或确认(ACK)未及时到达时,发送方应等待多久才能触发数据包的重传。 RTO通常由RTT计算而来,所以也是动态变化的。

TCP协议中,当一个数据段被发出之后,发送端就打开一个计时器,当计时器超过RTO之后,就重新发送这个段。 如何计算RTO呢?

发送端会实时的对 往返时延RTT进行采样,记录每次数据段从发送到接收到ACK所用的时间。但是这个时间还不能直接使用,需要做一个"平滑处理"

为什么要平滑处理? 我们需要当RTT变动的时候,重传时间能逐渐的改变,而不是立刻跳变,通常使用 SRTT ( Smoothed Round Trip Time )来表示这个平滑之后的值 其计算公式为

      SRTT = ( 1- \alpha ) * SRTT_{old} + \alpha * RTT

即,SRTT的值,通常由旧的 SRTT值和当前新菜样的 RTT计算而来,通常情况下 

\alpha = 0.125

举个例子,初始状态下 SRTT默认为 100ms,那么第一次菜样的RTT为 150ms时,

SRTT= ( 1 - 0.125 ) * 100 + 0.125 * 150 = 106.25ms 

可以看到,SRTT的值没有立刻跳变到 150ms 而是逐渐的增加到 150ms, 减少瞬时波动的影响

但是,RTO的计算不只依靠SRTT还需要 RTTV ( Round Trip Time Variation ) 即RTT的方差

RTTV = ( 1 - \beta ) * RTTV_{old} + \beta * | RTT - SRTT |   其中   \beta = 0.25

设置 RTTV的目的,也是降低网络动态波动时造成的影响。比如网络传输速度突然变快,此时如果不使用RTTV,会导致RTO迅速变小,数据过早的重新传输

最后通过公式 RTO = SRTT * 4 RTTV 计算出 最终的RTO超时时间 

滑动窗口

TCP协议的通讯双方,会为每一个链路设置一个发送缓冲区和接受缓冲区,上层协议(如 HTTP)只需要将需要发送的数据写如缓冲区,就不用关心后续操作,TCP会从缓冲区中依次读取数据并且发送,而接受端在TCP层,只需要将数据写入缓冲区,上层协议从缓冲区中读取数据即可。

停止与等待

最早的TCP协议,当发送端发送缓冲区中第一个段之后,必须等待接受端返回ACK之后,才能继续发送缓冲区中下一个段的内容,也就是 "停止与等待协议" 这种方式无疑是低效的。

为了提高效率,TCP引入了滑动窗口的概念,发送和接收双方都维护一个窗口,代表发送缓冲区和接收缓冲区可以发送/接收的范围。 用这种方式,发送方和接收方可以一次性发送和接收多个段的内容,提高了效率。

回退N帧 Go Back N 

这种方式是选择重传的进阶版本,对发送方设置一个发送窗口,使其一次性可以发送多个段,而接收方只有一个窗口,一次性只能接收一个段。这种方式就要求接收端必须按照顺序接收,如果某个后面的段优先到达, 那么接受端就会抛弃这个段。

发送端如果发现某个段超时了,就会重新发送这个段以及后续的所有段,这也就是会退N的由来,即会退到发送错误的那个段并且重新开始发送。

假设窗口大小为 2 需要发送三个段

 发送端可以一次性发送2个段,即WINDOW_SIZE= 2

接收端一个一个接收,每次接收后,后移接收窗口并且返回ACK,发送方收到ACK之后,后移发送窗口,发送窗口内新增的段3

 接收到段2,接收窗口后移,并且发送ACK,准备接收段3,发送端接收到ACK之后,后移发送窗口,以此类推... 

为了提高效率,接受端也可能在接收到多个段之后,再次发送最后收到段的ACK,发送端接收到之后,就默认前面的段已经都发送完了,减少了ACK的次数,这个也称为 累积确认

如果前面的段丢失了,那么后面收到的段也不会接收,直接丢弃

发送端迟迟未收到ACK,在计时器到达RTO后,从窗口开始的位置重新发送

这种方式提升了发送端的效率,但是由于接受端只能按照顺序接收段,就导致后到达的段被白白抛弃,造成浪费。

选择重传和SACK

 上述问题的本质是,接受端的缓冲区大小为1,而且只能按顺序接收。选择重传协议将接受端接收窗口也进行扩大,通常我们称为 rwnd,并且接受端可以不按照顺序接收段,但是需要按顺序确认。

也就是说,接受端接收到不连续的段也会保存,但是只会按顺序ACK。 比如接受端接收到3号段,这个时候来了5号,此时5号也会被接收,但是依旧返回ACK=4 即期待接收4号段

但是这里存在一个问题,接受端接收了5号并且保存,但是如何告知发送端5号已经被接收了呢? 如果不告知发送端,其会在超时之后继续发送5号,造成浪费。

这就要引入SACK,一个SACK占用8字节,表示接收段的[开始序号- 结束序号] 由于TCP序号占用4字节,所以SACK也需要占用 [4 字节, 4字节]

SACK被放在TCP段头部的扩展字段,也就是20字节之后的位置,这就需要数据偏移字段对段头部进行扩展。

我们知道,段头部最长为60字节,也就是数据偏移为 1111 = 15 15*4字节 = 60字节

所以,留给SACK的长度为 60 - 20 = 40字节,而通常情况下, 偏移段头部还需要携带其他的信息,所以一个段最多携带 4个SACK段。 也就是说,一个ACK段可以告诉发送方4段已经接收到的不连续的段序号。

如下,2号段丢失 , 3 4 到达后依旧被接收,只不过ACK依旧为 1460 并且携带SACK范围: 2920 - 4380 (代表 3 4 段已经接收)

接受端后移接收窗口,  发送端在收到ACK之后,后移发送窗口,此时5号可以被继续发送。2号段的定时器超时后,发送端重新发送段2 如下:

接受端收到段2之后,发送ACK=5840的累积确认,表示段 2 3 4也接收完成! 发送端收到后,移动发送端口到段5的位置,等待段5的ACK

上面我们提到,接受端的TCP层只负责把接受完的段放到缓冲区,等待上层协议取走。

如果上层协议不取走, 或者发送的很快,接受端的缓冲区满了。 此时如果发送端还在继续发送数据,接受端只能丢弃,造成浪费。

所以,接受端会在应答段的头部WINDOW_SIZE字段记录当前接受端剩余窗口大小,也就是当前还能接收的长度,这个长度是随着接受端接收数据动态变化的,发送端会按照这个接受端的窗口尺寸动态调整发送窗口的大小。

如下,缓冲区长度假设为4。段2丢失,此时接受端只能应答段1 而段3 4 虽然接受了,但是不能交给上层协议,会被暂存在缓冲区中,此时缓冲区还可以接受2个段,所以应答内容为 ACK = 1460 同时 WINDOW_SIZE = 2 

接受端收到ACK = 1460后,可以确定段1已经发送完成,后移发送缓冲区, 同时调整发送缓冲区大小为 2 ,在定时器超时之后,重新发送段2

接收段收到段2之后,累积确认 1 2 3 4 5的段都已经收到,交给上层协议。

此时接受窗口空闲,调整其尺寸为 4 并且后移。并且返回的ACK中,WINDOW_SIZE设置为4

发送端收到接收窗口尺寸扩大的应答,也扩大发送窗口并后移,继续发送段5

通过这种方式,即可实现通讯双方的流量控制,接收方通过告诉发送方自己的接收能力,来动态的调整发送方的发送行为。 

拥塞控制

和流量控制不同,拥塞控制目的在解决发送双方之间链路上的堵塞问题,TCP设计了一套机制,当链路中发生拥堵时,跑在上面的所有采用TCP协议通讯的主机都会降低发送速率,以保证链路的相对通畅。

拥塞窗口 cwnd

上面我们提到,接收方会在应答中携带WINDOW_SIZE 来改变发送方窗口的大小,但是发送方的窗口大小不一定完全等于接收方的窗口大小,还要考虑到链路拥塞的情况。

发送端会维护一个 拥塞窗口的尺寸 (cwnd)这个尺寸会随链路拥塞状态变化,而最终发送窗口的尺寸,由拥塞窗口和接受窗口共同决定 即 发送窗口的尺寸为 接受窗口 和 拥塞窗口尺寸的最小值 

                                           swnd = MIN( cwdn , rwnd ) 

发送端只需要控制拥塞窗口的大小,就可以调整发送窗口的尺寸,从而调整发送速率

慢开始&拥塞避免

拥塞窗口的尺寸是随着链路的拥塞状态动态调整的,其策略就是 慢开始 和 拥塞避免

慢开始,指的是TCP协议在刚开始发送数据时,会以一个较小的拥塞窗口尺寸开始发送,并且每次收到一个ACK后,拥塞窗口尺寸 + 1 ,比如

第一次窗口尺寸是 1 发送一个段

第一个段的ACK收到后,增加尺寸到 2 这次可以一次性发送2个段

这两个段的ACK收到后,增加尺寸到4,一次发送4个段,以此类推

可以看到,慢开始阶段的拥塞窗口尺寸以 1 2 4 8 16 ... 这样指数级别快速增长!

如下图所示

但是,拥塞窗口的尺寸不能一直增长,通常会设置一个 慢开始阀值 ssthreshold ( slow start threshold ) 当慢增长到达这个阀值,就会转换到拥塞避免阶段,这个阶段会线性的增加拥塞窗口的大小,直到拥塞产生

 

什么时候产生拥塞? TCP定义的是,当出现丢包发生冲传时,就默认链路中产生了拥塞,此时就需要

  1. 调整 ssthreshold的值为当前拥塞窗口的一半
  2.  重新开始慢开始的阶段,如下图

第一次的。ssthreshold为16,拥塞窗口慢开始到16后,开始拥塞避免阶段,线性扩大窗口尺寸。当尺寸到达24时发生超时现象,此时调整 ssthrehold = 12 并且重新开始慢开始的过程,扩大到新的 ssthrehold=12之后,转换到拥塞避免的线性增长,直到下一次拥塞(丢包)

快重传&快恢复

这样的方式可以有效避免TCP链路中的拥塞现象,但是早先版本的发生拥塞就将拥塞窗口尺寸设置为初始状态会导致拥塞窗口恢复过慢,降低效率,新版的TCP RENO版本增加了快速重传和快恢复的机制。

当接受端收到不连续的段时,会立刻发送ACK响应,让发送端知道当前存在丢失的段,如下

1号段在传输过程中丢失,而接收方能正确收到 2 3 4 号段,在每次收到不连续的段时,接收放都会响应 ACK=0 即接收方渴望得到 0 号段,这样ack=0会在接收方接收到 2 3 4 号段之后响应给发送方3次

发送方在3次接收到同一个ACK之后,会忽略计时器立刻重传这个段,表示接收方迫切需要这个段,这也就是快速冲传,无需等待计时器,如下:

同时,在发生快速重传时,拥塞窗口的 ssthreshold被调整为 (1/2)cwnd 但是这次拥塞窗口不会从初始状态重新增长,而是调整到新的 ssthreold未知,并且直接开始线性的拥塞避免增长,这就称为快恢复,如下图所示。 

当前的 TCP Reno结合了上述的 慢开始 拥塞避免 以及快重传和快恢复

当响应超时时,tcp会从初始状态慢开始调整拥塞窗口大小

当接收到三个连续的ACK之后,会快速重新传递丢失的段,并且从 ssthreold的位置快速恢复拥塞窗口的尺寸! 


网站公告

今日签到

点亮在社区的每一天
去签到