
本文共 11490 字,大约阅读时间需要 38 分钟。
【网络通信 -- 直播】网络通信协议简介 -- TCP 传输控制协议
【1】TCP 的特点
TCP提供一种面向连接的、可靠的字节流服务;
面向连接意味着 : 两个使用TCP的应用在彼此交换数据之前必须先建立一个TCP连接,在一个TCP连接中,仅有两方进行彼此通信
TCP提供可靠性保证的方式:
1. 应用数据被分割成TCP认为最适合发送的数据块
2. 当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段,如果不能及时收到一个确认,将重发这个报文段;
3. 当TCP收到发自TCP连接另一端的数据,它将发送一个确认,这个确认不是立即发送,通常将推迟几分之一秒;
4. TCP将保持它首部和数据的检验和,这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化,如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段(希望发端超时并重发);
5. 既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序,如果必要,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层;
6. 既然IP数据报会发生重复,TCP的接收端必须丢弃重复的数据;
7. TCP还能提供流量控制,TCP连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据,这将防止较快主机致使较慢主机的缓冲区溢出;
【2】TCP 的部首
1) 16 位端口号 : 告知主机该报文段是来自哪里(源端口Source Port) 以及传给哪个上层协议或应用程序 (目的端口 Destination Port) 的,进行 TCP 通信时,客户端通常使用系统自动选择的临时端口号,而服务器则使用知名服务端口号(比如 DNS 协议对应端口 53,HTTP 协议对应 80,这些端口号可在 /etc/services 文件中找到);
2) 32位序号 : 一次 TCP 通信 (从 TCP 连接建立到断开) 过程中某一个传输方向上的字节流的每个字节的编号,假设主机 A 和主机 B 进行 TCP 通信,A 发送给 B 的第一个 TCP 报文段中,序号值被系统初始化为某个随机值 ISN (Initial Sequence Number,初始序号值), 那么在该传输方向上 (从 A 到 B),后续的 TCP 报文段中序号值将被系统设置成 ISN 加上该报文段所携带数据的第一个字节在整个字节流中的偏移;例如,某个 TCP 报文段传送的数据是字节流中的第 1025~2048 字节,那么该报文段的序号值就是 ISN+1025;另外一个传输方向(从 B 到 A)的 TCP 报文段的序号值也具有相同的含义;
3) 32位确认号(acknowledgement number) : 用作对另一方发送来的 TCP 报文段的响应;其值是收到的 TCP 报文段的序号值加 1;假设主机 A 和主机 B 进行 TCP 通信,那么 A 发送出的 TCP 报文段不仅携带自己的序号,而且包含对 B 发送来的 TCP 报文段的确认号;反之,B 发送出的 TCP 报文段也同时携带自己的序号和对 A 发送来的报文段的确认号;
4) 4位头部长度(header length) : 标识该 TCP 头部有多少个 32bit 字(4字节);因为4位最大能标识15,所以 TCP 头部最长是 60 字节;
5) 6位标志位包含如下几项 :
URG标志,表示紧急指针(urgent pointer)是否有效;
ACK标志,表示确认号是否有效;我们称携带 ACK 标识的 TCP 报文段为确认报文段
PSH标志,提示接收端应用程序应该立即从 TCP 接收缓冲区中读走数据,为接收后续数据腾出空间(如果应用程序不将接收到的数据读走,它们就会一直停留在 TCP 接收缓冲区中);
RST标志,表示要求对方重新建立连接,称携带 RST 标志的 TCP 报文段为复位报文段;
SYN标志,表示请求建立一个连接,称携带 SYN 标志的 TCP 报文段为同步报文段;
FIN标志,表示通知对方本端要关闭连接了,称携带 FIN 标志的 TCP 报文段为结束报文段;
6) 16位窗口大小(window size) : 是 TCP 流量控制的一个手段,此处的窗口,指的是接收通告窗口(Receiver Window,RWND),告诉对方本端的 TCP 接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度;
7) 16位校验和(TCP check sum) : 由发送端填充,接收端对 TCP 报文段执行 CRC 算法以检验 TCP 报文段在传输过程中是否损坏;注意,这个校验不仅包括TCP头部,也包括数据部分,这也是 TCP 可靠传输的一个重要保障;
8) 16位紧急指针(urgent pointer) : 是一个正的偏移量,它和序号字段的值相加表示最后一个紧急数据的下一字节的序号;因此,确切地说,这个字段是紧急指针相对当前序号的偏移,不妨称之为紧急偏移;TCP 的紧急指针是发送端向接收端发送紧急数据的方法;
9) TCP 头部选项 : TCP 头部的最后一个选项字段(options)是可变长的可选信息;
kind=0 是选项表结束选项;
kind=1 是空操作(nop)选项,没有特殊含义,一般用于将 TCP 选项的总长度填充为 4 字节的整数倍;
kind=2 是最大报文段长度选项,TCP 连接初始化时,通信双方使用该选项来协商最大报文段长度(Max Segement Size,MSS),TCP 模块通常将 MSS 设置为(MTU-40)字节(减掉的这 40 字节包括 20 字节的 TCP 头部和 20 字节的 IP 头部),这样携带 TCP 报文段的 IP 数据报的长度就不会超过 MTU (假设 TCP 头部和 IP 头部都不包含选项字段,并且这也是一般情况),从而避免本机发生 IP 分片;对以太网而言,MSS 值是 1460 (1500-40)字节;
kind=3 是窗口扩大因子选项,TCP 连接初始化时,通信双方使用该选项来协商接收通告窗口的扩大因子;在 TCP 的头部中,接收通告窗口大小时用 16 位表示的,故最大为 65535 字节,但实际上 TCP 模块允许的接收通告窗口大小远不止这个数 (为了提高 TCP 通信的吞吐量),窗口扩大因子解决了这个问题;假设 TCP 头部中的接收通告窗口大小是 N 乘 2 的 M 次方,或者说 N 左移 M 位;注意,M 的取值范围是 0~14,可以通过修改 /proc/sys/net/ipv4/tcp_window_scaling 内核变量来启用或关闭窗口扩大因子选项;
kind=5 是 SACK 实际工作的选项,该选项的参数告诉发送方本端已经收到并缓存的不连续的数据块,从而让发送端可以据此检查并重发丢失的数据块;每个块边沿(edge of block) 参数包含一个 4 字节的序号;其中块左边沿表示不连续块的第一个数据的序号,而块右边沿则表示不连续块的最后一个数据的序号的下一个序号;这样一对参数 (块左边沿和块右边沿) 之间的数据是没有收到的;因为一个块信息占用 8 字节,所以 TCP 头部选项中实际上最多可以包含 4 个这样的不连续数据块(考虑选项类型和长度占用的 2 字节);
kind=8 是时间戳选项,该选项提供了较为准确的计算通信双方之间的回路时间 (Round Trip Time,RTT) 的方法,从而为 TCP 流量控制提供重要信息,我们可以通过修改 /proc/sys/net/ipv4/tcp_timestamps 内核变量来启用或关闭时间戳选项;
【3】TCP 状态转移与连接的建立、中止
1. 对于建链接的3次握手:主要是要初始化 Sequence Number 的初始值,通信的双方要互相通知对方自己的初始化的 Sequence Number(缩写为ISN:Inital Sequence Number),SYN(Synchronize Sequence Numbers)即上图中的 x 和 y,这个号要作为以后的数据通信的序号,以保证应用层接收到的数据不会因为网络上的传输的问题而乱序(TCP会用这个序号来拼接数据);
2. 对于4次挥手:其实是2次,因为TCP是全双工的,发送方和接收方都需要 Fin 和 Ack,只不过,有一方是被动的,所以看上去就成了所谓的4次挥手;
3. 关于建连接时SYN超时:如果server端接到了clien发的SYN后回了SYN-ACK后client掉线了,server端没有收到client回来的ACK,那么,这个连接处于一个中间状态,既没成功,也没失败;于是,server端如果在一定时间内没有收到的TCP会重发SYN-ACK,在Linux下,默认重试次数为5次,重试的间隔时间从1s开始每次都翻倍,5次的重试时间间隔为1s, 2s, 4s, 8s, 16s,总共31s,第5次发出后还要等32s都知道第5次也超时了,所以,总共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 2^6 -1 = 63s,TCP才会把断开这个连接;
4. 最大报文段长度(MSS):TCP传往另一端的最大块数据的长度,当一个连接建立时,连接的双方都要通告各自的MSS;
5. 在TCP的状态图中,从TIME_WAIT状态到CLOSED状态,有一个超时设置,这个超时设置是 2*MSL,为什么要这有TIME_WAIT?主要有两个原因:1)TIME_WAIT确保有足够的时间让对端收到了ACK,如果被动关闭的那方没有收到Ack,就会触发被动端重发Fin,一来一去正好2个MSL,2)有足够的时间让这个连接不会跟后面的连接混在一起【详见 】;
6. 平静时间的概念:TCP在重启动后的MSL秒内不能建立任何连接,问题描述,如果使用处于2MSL等待端口的主机出现故障,它会在MSL秒内重新启动,并立即使用故障前仍处于2MSL的插口对来建立一个新的连接,若如此则在故障前从这个连接发出而迟到的报文段会被错误地当作属于重启后新连接的报文段;
难点总结
1. TCP 连接的初始化序列号能否固定
ISN(Inital Sequence Number)和一个假的时钟绑在一起,这个时钟会在每4微秒对ISN做加一操作,直到超过2^32,又从0开始,这需要4小时才会产生ISN的回绕问题,这几乎可以保证每个新连接的ISN不会和旧的连接的ISN产生冲突,现在的实现大多是在一个基准值的基础上进行随机的;
2. TIME_WAIT 带来的问题
TIME_WAIT带来的问题主要源于,一个连接进入TIME_WAIT状态后需要等待2*MSL(一般是1到4分钟)的时间才能断开连接释放连接占用的资源,因此会造成以下问题:
- 1) 作为服务器,短时间内关闭了大量的Client连接,就会造成服务器上出现大量的TIME_WAIT连接,严重消耗着服务器的资源;
- 2) 作为客户端,短时间内大量的短连接,会大量消耗的Client机器的端口,毕竟端口只有65535个,端口被耗尽了,后续将无法在发起新的连接;
3. TIME_WAIT的快速回收和重用
TIME_WAIT的快速回收
linux下开启TIME_WAIT快速回收需要同时打开tcp_tw_recycle和tcp_timestamps(默认打开)两选项,Linux下快速回收的时间为3.5 * RTO(Retransmission Timeout),而一个RTO时间为200ms至120s;
拒绝新连接需要同时满足以下三个条件
- 1)来自同一个对端Peer的TCP包携带了时间戳;
- 2)之前同一台peer机器(仅仅识别IP地址,因为连接被快速释放了,没了端口信息)的某个TCP数据在MSL秒之内到过本Server;
- 3)Peer机器新连接的时间戳小于peer机器上次TCP到来时的时间戳,且差值大于重放窗口戳(TCP_PAWS_WINDOW);
特殊情况 : 在一个NAT后面的所有Peer机器在Server看来都是一个机器,NAT后面的那么多Peer机器的系统时间戳很可能不一致,有些快,有些慢,这样,在Server关闭了与系统时间戳快的Client的连接后,在这个连接进入快速回收的时候,同一NAT后面的系统时间戳慢的Client向Server发起连接,这就很有可能同时满足上面的三种情况,造成该连接被Server拒绝掉;
TIME_WAIT的重用
只要满足下面两点中的一点,一个TW状态的四元组(即一个socket连接)可以重新被新到来的SYN连接使用:
- 1)新连接SYN告知的初始序列号比TIME_WAIT老连接的末序列号大;
- 2)如果开启了tcp_timestamps,并且新到来的连接的时间戳比老连接的时间戳大;
注意 :要同时开启tcp_tw_reuse选项和tcp_timestamps 选项才可以开启TIME_WAIT重用;
tcp_tw_reuse 和 SO_REUSEADDR 选项对比
两者是两个完全不同的概念,tcp_tw_reuse是内核选项,而SO_REUSEADDR用户态的选项,使用SO_REUSEADDR是告诉内核,如果端口忙,但TCP状态位于 TIME_WAIT ,可以重用端口;如果端口忙,而TCP状态位于其他状态,重用端口时依旧得到一个错误信息, 指明Address already in use”;
【3.1】TCP 的半关闭
TCP的半关闭:TCP提供的连接的一端在结束它的发送后还能接收来自另一端数据的能力;
【3.2】TCP 双方同时建立连接
【3.3】TCP 双方同时关闭连接
【4】TCP 的交互数据流
【4.1】经受时延的确认
通常TCP在接收到数据时并不立即发送ACK,相反,它推迟发送,以便将ACK与需要沿该方向发送的数据一起发送(这种现象为数据捎带ACK),绝大多数实现采用的时延为200 ms,也就是说,TCP将以最大200 ms的时延等待是否有数据一起发送;
难点总结
1. TCP的延迟确认机制
按照TCP协议,确认机制是累积的,也就是确认号X的确认指的是所有X之前但不包括X的数据已经收到了;确认号(ACK)本身就是不含数据的分段,因此大量的确认号消耗了大量的带宽,虽然大多数情况下,ACK还是可以和数据一起捎带传输的,但是如果没有捎带传输,那么就只能单独回来一个ACK,如果这样的分段太多,网络的利用率就会下降;延迟的ACK即ACK在收到数据后并不马上回复,而是延迟一段可以接受的时间,看能不能和接收方要发给发送方的数据一起回去,因为TCP协议头中总是包含确认号的,如果能的话,就将数据一起捎带回去,这样网络利用率就提高了;
延迟ACK就算没有数据捎带,那么如果收到了按序的两个包,那么只要对第二包做确认即可,这样也能省去一个ACK消耗;由于TCP协议不对ACK进行ACK的,RFC建议最多等待2个包的积累确认,这样能够及时通知对端Peer,我这边的接收情况;
ACK分段的确认号,是确认按序收到的最后一个字节序,对于乱序到来的TCP分段,接收端会回复相同的ACK分段,只确认按序到达的最后一个TCP分段,TCP连接的延迟确认时间一般初始化为最小值40ms,随后根据连接的重传超时时间(RTO)、上次收到数据包与本次接收数据包的时间间隔等参数进行不断调整;
【4.2】Nagle 算法
Nagle 算法要求一个TCP连接上最多只能有一个未被确认的未完成的小分组,在该分组的确认到达之前不能发送其他的小分组,相反,TCP收集这些少量的分组,并在确认到来时以一个分组的方式发出去,该算法的优越之处在于它是自适应的:确认到达得越快,数据也就发送得越快;
【5】TCP 的成块数据流
【5.1】快的发送方与慢的接收方
【6】TCP 的流量控制
【6.1】滑动窗口
TCP头里有一个字段叫Window,又叫Advertised-Window,这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据,于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来;
1. 接收端LastByteRead指向了TCP缓冲区中读到的位置,NextByteExpected指向的地方是收到的连续包的最后一个位置,LastByteRcved指向的是收到的包的最后一个位置,中间有些数据还没有到达,存在数据空白区;
2. 发送端的LastByteAcked指向了被接收端Ack过的位置(表示成功发送确认),LastByteSent表示发出去了,但还没有收到成功确认的Ack,LastByteWritten指向的是上层应用正在写的地方;
3. 接收端在给发送端回ACK中会汇报自己的AdvertisedWindow = MaxRcvBuffer – LastByteRcvd – 1;
4. 发送方会根据这个窗口来控制发送数据的大小,以保证接收方可以处理;
窗口左右边沿移动的术语
1. 窗口合拢,窗口左边沿向右边沿靠近,这种现象发生在数据被发送和确认时;
2. 窗口张开,当窗口右边沿向右移动时将允许发送更多的数据,这种现象发生在另一端的接收进程读取已经确认的数据并释放了TCP的接收缓存时;
3. 窗口收缩,窗口右边沿向左移动;
滑动窗口移动图示
滑动窗滑动后的示意图
#1 已收到ack确认的数据;
#2 发还没收到ack的;
#3 在窗口中还没有发出的(接收方还有空间);
#4 窗口以外的数据(接收方没空间);
【6.2】接受端控制发送端的图示
Zero Window
若Window变成0了,TCP发送端就不发数据了,TCP使用Zero Window Probe技术,缩写为ZWP,探测窗口大小是否不为0,即发送端在窗口变成0后,会发ZWP的包给接收方,让接收方来ack其Window尺寸,一般这个值会设置成3次,每次大约30-60秒,如果3次过后还是0的话,有的TCP实现就会发RST端口链接;
Silly Window Syndrome
1. 如果这个问题是由Receiver端引起的,则在receiver端,如果收到的数据导致window size小于某个值,可以直接ack(0)回sender,这样就把window给关闭了,也阻止了sender再发数据过来,等到receiver端处理了一些数据后windows size 大于等于了MSS,或者 receiver buffer有一半为空,就可以把window打开让send 发送数据过来;
2. 如果这个问题是由Sender端引起的,那么采用 Nagle’s algorithm,这个算法的思路也是延时处理,两个主要的条件:1)要等到 Window Size>=MSS 或是 Data Size >=MSS,2)收到之前发送数据的ack回包,才会发数据,否则就是在攒数据;
【7】TCP 的重传机制
【7.1】TCP 的重传超时计算
为了使重传机制更高效,如果能够比较准确知道在当前网络状况下,一个数据包从发出去到回来的时间 RTT——Round Trip Time,那么根据该 RTT 就可以方便设置TimeOut——RTO(Retransmission TimeOut);
RTO 的经典算法
1)首先采样计算RTT值;
2)然后计算平滑的RTT,称为Smoothed Round Trip Time (SRTT),SRTT = ( ALPHA*SRTT ) + ((1-ALPHA)*RTT);
3)RTO = min[UBOUND,max[LBOUND,(BETA*SRTT)]];
其中:UBOUND是RTO值的上限;LBOUND是RTO值的下限;ALPHA 平滑因子(e.g., .8 to .9), BETA 延迟方差因子(e.g., 1.3 to 2.0);
改进算法 Jacobson / Karels Algorithm
SRTT = SRTT + α (RTT – SRTT) —— 计算平滑RTT;
DevRTT = (1-β)DevRTT + β(|RTT-SRTT|) ——计算平滑RTT和真实的差距(加权移动平均);
RTO= μ SRTT + ∂ DevRTT
(其中:在Linux下,α = 0.125,β = 0.25, μ = 1,∂ = 4)
每一个TCP连接单一超时定时器的设计的算法规则
1)每一次一个包含数据的包被发送(包括重发),如果还没开启重传定时器,则开启它,使得它在RTO秒之后超时(按照当前的RTO值);
2)当接收到一个ACK确认一个新的数据, 如果所有的发出数据都被确认了,关闭重传定时器;
3)当接收到一个ACK确认一个新的数据,还有数据在传输,也就是还有没被确认的数据,重新启动重传定时器,使得它在RTO秒之后超时(按照当前的RTO值);
4)当重传定时器超时后,依次做下列3件事情:
4.1)重传最早的尚未被TCP接收方ACK的数据包
4.2)重新设置RTO 为 RTO * 2(“还原定时器”),但是新RTO不应该超过RTO的上限(RTO有个上限值,这个上限值最少为60s)
4.3)重启重传定时器
上面的建议算法体现了一个原则:没被确认的包必须可以超时,并且超时的时间不能太长,同时也不要过早重传;
【7.2】TCP 的重传机制
Selective Acknowledgment (SACK,选择确认)机制,SACK是TCP的扩展选项,包括:
- 1)SACK允许选项(Kind=4,Length=2,选项只允许在有SYN标志的TCP包中);
- 2)SACK信息选项(Kind=5,Length);
D-SACK 利用第一块SACK数据中描述重复接收的不连续数据块的序列号参数,其他SACK数据则描述其他正常接收到的不连续数据,这样发送方利用第一块SACK,可以发现数据段被网络复制、错误重传、ACK丢失引起的重传、重传超时等异常的网络状况,使得发送端能更好调整自己的重传策略;
D-SACK 的优点:
- 1)发送端可以判断出,是发包丢失了,还是接收端的ACK丢失了;(发送方,重传了一个包,发现并没有D-SACK那个包,那么就是发送的数据包丢了;否则就是接收端的ACK丢了,或者是发送的包延迟到达了);
- 2)发送端可以判断自己的RTO是不是有点小了,导致过早重传(如果收到比较多的D-SACK就该怀疑是RTO小了);
- 3)发送端可以判断自己的数据包是不是被复制了(如果明明没有重传该数据包,但是收到该数据包的D-SACK);
- 4)发送端可以判断目前网络上是不是出现了有些包被delay了,也就是出现先发的包却后到了;
【8】TCP 拥塞的处理
【8.1】网络阻塞的原因
对于TCP,端到端的流量控制必然会导致网络拥堵,这是因为TCP只看到对端的接收空间的大小,而无法知道链路上的容量,只要双方的处理能力很强,那么就可以以很大的速率发包,于是链路很快出现拥堵,进而引起大量的丢包,丢包又引发发送端的重传风暴,进一步加剧链路的拥塞;
链路上的转发节点,例如路由器,再好的路由器只要接入网络,总是会拉低网络的总带宽,如果在路由器节点上出现处理瓶颈,那么就很容易出现拥塞;
【8.2】冗余ACK的判定条件(对于SACK,那么根据SACK的一些信息来进一步判断)
[1] 接收ACK的那端已经发出了一些还没被ACK的数据包
[2] 该ACK没有捎带data
[3] 该ACK既不是SYN包的ACK也不是FIN包的ACK
[4] 该ACK的确认号等于接收ACK那端已经收到的ACK的最大确认号
[5] 该ACK通知的窗口等于接收该ACK的那端上一个收到的ACK的窗口
【8.3】Reno 算法包含4个部分
[1]慢热启动算法 – Slow Start;
[2]拥塞避免算法 – Congestion Avoidance;
[3]快速重传 - Fast Retransimit;
[4]快速恢复算法 – Fast Recovery;
【8.3.1】慢启动
慢启动算法流程
- 1)连接建好先初始化cwnd = N,表明可以传N个MSS大小的数据;
- 2)每当收到一个ACK,cwnd++; 呈线性上升;
- 3)每当过了一个RTT,cwnd = cwnd*2; 呈指数让升;
- 4)ssthresh(slow start threshold)是一个上限,当cwnd >= ssthresh时,就会进入“拥塞避免算法”;
根据 RFC5681,如果MSS > 2190 bytes,则N = 2; 如果MSS < 1095 bytes,则N = 4; 如果2190 bytes >= MSS >= 1095 bytes,则N = 3; 一篇Google的论文《An Argument for Increasing TCP’s Initial Congestion Window》建议把cwnd 初始化成了 10个MSS,Linux 3.0后采用了这篇论文的建议。
【8.3.2】拥塞避免
拥塞避免算法流程
- 1)收到一个ACK时,cwnd = cwnd + 1/cwnd
- 2)当每过一个RTT时,cwnd = cwnd + 1
【8.3.3】拥塞发生
TCP是看不到网络的整体状况的,那么TCP认为网络拥塞的主要依据是它重传了报文段;
拥塞发生处理流程
1)出现RTO超时,重传数据包,这种情况下,TCP就认为出现拥塞的可能性就很大:
- sshthresh = cwnd /2
- cwnd 重置为 1
- 进入慢启动过程
2)在RTO超时前,收到3个duplicate ACK进行重传数据包,这种情况下,收到3个冗余ACK后说明确实有中间的分段丢失,然而后面的分段确实到达了接收端,因为这样才会发送冗余ACK,这一般是路由器故障或者轻度拥塞或者其它不太严重的原因引起的,因此此时拥塞窗口缩小的幅度就不能太大,此时进入快速重传;
【8.3.4】快速重传
- 1) 调整门限ssthresh的值为当前cwnd值的1/2;
- 2) 将cwnd值设置为新的ssthresh的值;
- 3) 重新进入拥塞避免阶段;
在快速重传的时候,一般网络只是轻微拥堵,在进入拥塞避免后,cwnd恢复的比较慢,针对这个,“快速恢复”算法被添加进来,当收到3个冗余ACK时,TCP最后的[3]步骤进入的不是拥塞避免阶段,而是快速恢复阶段;
【8.3.5】快速恢复
快速恢复算法流程
- cwnd = sshthresh + 3 * MSS (3的意思是确认有3个重传Duplicated ACKs指定的数据包被收到了)
- 如果再收到 duplicated Acks,那么cwnd = cwnd +1
- 如果收到了新的Ack,那么,cwnd = 快速重传阶段1的 sshthresh 值,然后就进入拥塞避免的算法
New Reno算法,该算法是在没有SACK的支持下改进Fast Recovery算法(SACK改变TCP的确认机制,把乱序等信息会全部告诉对方,SACK本身携带的信息就可以使得发送方有足够的信息来知道需要重传哪些包,而不需要重传哪些包)
- 1)发送端收到3个冗余ACK后,重传冗余ACK指示可能丢失的那个包segment1,如果segment1的ACK通告接收端已经收到发送端的全部已经发出的数据,那么就是只丢失一个包,如果没有,那么就是有多个包丢失了;
- 2)发送端根据segment1的ACK判断出有多个包丢失,那么发送端继续重传窗口内未被ACK的第一个包,直到sliding window内发出去的包全被ACK了,才真正退出Fast Recovery阶段;
参考致谢
本博客为博主的学习实践总结,并参考了众多博主的博文,在此表示感谢,博主若有不足之处,请批评指正。
【1】TCP/IP详解 卷1:协议
【2】
【3】
【4】
【5】
发表评论
最新留言
关于作者
