本章目录
- 4. TCP连接
- 4.1 TCP报文段的首部格式
- 4.2 TCP连接如何保证可靠
- 4.3 ARQ协议
- 4.3.1 停止等待ARQ协议
- 4.3.1.1 无差错情况
- 4.3.1.2 出现差错情况
- 4.3.1.3 确认丢失和确认迟到
- 4.3.2 连续ARQ协议
- 4.3.2.1 流水线传输
- 4.3.2.2 累积确认
- 4.3.2.3 滑动窗口协议
- 4.3.3 停止等待ARQ和连续ARQ的对比
- 4.3.4 ARQ到底运行在那一层?
- 4.4 三次握手
- 4.4.1 三次握手的步骤
- 4.4.2 三次握手的作用
- 4.4.3 为什么需要最后一次握手
- 4.4.4 如果已经建立了连接,但是客户端突然故障了怎么办
- 4.4.5 三次握手时报文的初始化序号(ISN)是固定的吗
- 4.4.6 什么是半连接队列
- 4.4.7 三次握手过程中可以携带数据吗
- 4.5 四次挥手
- 4.5.1 四次挥手的步骤
- 4.5.2 为什么最后客户端要等待2*MSL
- 4.6 为什么建立连接是三次握手,而释放连接是四次挥手
- 4.7 流量控制
- 4.7.1 什么是流量控制
- 4.7.2 如何实现流量控制
- 4.7.3 如何避免流量控制引发的死锁
- 4.8 拥塞控制
- 4.8.1 什么是拥塞控制
- 4.8.2 为什么需要拥塞控制
- 4.8.3 如何知道网络的拥塞情况
- 4.8.4 到达瓶颈值了怎么办
- 4.8.5 超时一定是网络拥塞吗
- 4.9 拥塞控制和流量控制的区别
4. TCP连接
4.1 TCP报文段的首部格式
传输层的TCP协议会将应用层交付下来的报文加上TCP首部,TCP首部有20字节的固定开销,以及有长度可变的部分。
源端口和目的端口各占2个字节,序号和确认号各占4个字节。
- 序号seq:序号seq用来表示从TCP发送方向接收方发送的字节流的起始序号
- TCP连接中传送的字节流中的每个字节都按顺序编号。
- 例如一段报文的序号seq=301,携带的数据长度为100字节,那么下一个报文段的数据序号应该从401开始。
- 确认号ack:==确认号ack是接收方期望收到发送方下一个报文段的第一个数据字节的序号。==只有当ACK=1时,确认序号字段才有效。
- 例如,S收到了C发送过来的seq=501的报文,而数据长度为200字节,这表明S应该正确收到了C发送过来的序号在[501,700]的数据。因此,S期望收到的C发送来的下一个数据序号为701,于是S在发送给C的确认报文段中把确认号置为701.
- 数据偏移:占4位,它指出TCP报文的数据距离TCP报文段的起始处有多远。
- 窗口:占2个字节,用来通知接收方,本报文需要有多大的空间来接收。
标识位:
- 确认标识ACK:用来标识数据包的成功接收。仅当ACK为1的时候,确认才有效。
- 复位标识RST:当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接;
- 同步标识SYN:建立连接时用来同步序号。当SYN=1,ACK=0时,表明这是一个连接请求报文;当SYN=1,ACK=1时,表示这是一个同意请求报文
- 终止标识FIN:FIN用来释放连接。当FIN=1时,表示此段报文发送方已发送完毕。
4.2 TCP连接如何保证可靠
校 序 重 流 拥
-
校验和
TCP会保持它的首部和数据的校验和,这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果发现校验和有差错,就会丢弃接此报文段,不对这个报文段进行确认。
-
确认应答和序列号
TCP传输时将每个字节的数据都进行了编号,这就是序列号。发送端按序发送报文,接收端按序收到报文后会给发送端一个ACK确认报文,并且该报文中带有ack,表示下一次发送端应该从哪个地方开始发送报文。
-
超时重传
发送端每发出一个报文段,就启动一个定时器。如果发送端发送的报文段一定时间内没有收到ACK确认,就会重新发送该报文段。如果接收端已经有了该报文段,就会丢弃刚刚发送过来的报文段。
超时重传保证报文即使丢失也能再传输,直到成功传输为止,从而保证可靠。
-
流量控制
发送端如果数据发送过快,导致接收端的缓冲区很快就满了,如果持续下去,数据溢出缓冲区,就会出现数据丢失。这时需要在发送端和接收端有一个窗口,窗口的作用为:在发送缓冲区,只有在窗口里面的数据,才能被发送,在接收缓冲区,只有在窗口里的数据才能被接收,接收端收到数据之后,会回复ack,发送端会根据ack的值来判断接收能力,从而动态调整窗口大小,实现流量控制。
-
拥塞控制
如果网络出现拥塞,TCP会根据不同情况,采用不同的算法:慢开始,拥塞避免,快重传,快恢复来对窗口大小cwnd和慢开始门限值ssthresh进行调整,从而降低网络拥塞的可能性。
4.3 ARQ协议
TCP保证可靠传输的确认应答和超时重传机制是靠ARQ协议实现的,ARQ协议:
-
ARQ(Automatic Repeat Quest)自动重传请求,是OSI模型中的错误纠正协议之一。
-
ARQ协议通过确认和重传这两个机制,在不可靠的基础上实现可靠的信息传输。
-
如果发送方在发送后的一段时间内没有收到确认帧,他通常会重新发送。
-
重传的请求是自动进行的,接收方不需要请求发送方重传某个出错的分组。
4.3.1 停止等待ARQ协议
“停止等待”就是每发送完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组。
停止等待协议ARQ的优缺点:
4.3.1.1 无差错情况
4.3.1.2 出现差错情况
如果出现差错,会有两种差错情况:
- B接收M1时检测出了差错,于是B就丢弃M1,其他什么也不做(不通知发送方A)
- M1在传输过程中丢失了,这时B什么也不知道,更什么也不做
这两种差错情况下,接收方B什么也不做。发送方A超过一段时间仍然没有收到确认,就认为刚刚的分组丢失了,就会重传之前这个未被确认的分组。这就是超时重传。
4.3.1.3 确认丢失和确认迟到
Note:确认是名词,指的是接收方给发送方发的ACK确认,不是动词-确定
如果出现了差错,发送方A进行了超时重传,那么接收方B假定收到了这个重传的分组M1。这时接收方B应该采取两个行动:
- 如果之前已经收到过分组M1,那么就会丢弃这个重复的分组M1,不向上交付,否则收下M1
- 向A发送确认
如果传输过程中没有出现差错,但是接收方B对分组M1的确认迟到了。那么由于超时重传,发送方A会收到重复的确认,对于收到的重复的确认发送方直接丢弃。
发送方A和接收方B是如何知道重复的,从而需要丢弃呢?——编号
- 发送方A为每一个发送的分组都进行编号。如果接收方B收到的重复编号的分组,就会将其丢弃,并回送确认。
- 接收方B对发送的确认也进行编号,指示该确认是对哪一个分组的确认。
4.3.2 连续ARQ协议
4.3.2.1 流水线传输
为了提高传输效率,发送方可以不采用低效率的停止等待协议,而是采用流水线传输,即发送方可以连续发送多个分组,不必每发送完一个分组就停顿下来等待对方的确认,这样可以使信道上一直有数据不间断地传送。
流水线传输通常要求:
- 必须增加序号范围。因为每个传输的分组必须有一个唯一的序号,可能存在有多个在传输中未确认的报文。
- 发送方和接收方要能缓存多个分组,发送方至少要能缓存那些已发送但是没有被确认的分组,接收方要能缓存那些已正确接收到的分组。
- 解决流水线传输的差错有两种滑动窗口协议:回退N(Go-back-N)和选择重传(SR)。
当使用流水线传输时,要使用连续ARQ协议和滑动窗口协议。
4.3.2.2 累积确认
累积确认:接收方不必对收到的分组逐个发送确认,而是对按序到达的最后一个分组发送确认,这就表示“到这个分组为止的所有分组都已经正确收到了”。
但同时累积确认也有缺陷,例如发送方传送了5个包,但是第3个包丢失了,第4和第5个正常。这时根据累积确认,接收方只能传送前两个包的ACK(按序到达的最后一个)。在接收到第2个包ACK的发送方不知道后面3个包是否到达,就会将后3个包全部进行重传,即:Go-back-N。
累积确认的优缺点:
- 优点:容易实现,即使ACK确认丢失也不必重传(指的是接收方不必重传)
- 缺点:不能向发送方反映出接收方已经正确收到的所有分组的信息(如上面的例子,只有中间的数据包丢失,后面的可能也被正确接收)
4.3.2.3 滑动窗口协议
滑动窗口协议以基于分组的数据传输协议为特征,因此该协议适用于对按顺序传输分组可靠性要求较高的环境。
- 提供TCP的可靠性(最基本的传输可靠性来源于“确认重传”机制),避免丢包
- 提供TCP的流控特性,用于网络数据传输时的流量控制,以避免拥塞的发生。
- 滑动窗口协议在发送方和接收方之间各自维持着一个滑动窗口,发送窗口和接收窗口,两个窗口大小不一定相同
- 使用滑动窗口协议控制发送方和接收方所能发送和接收的分组的数量和编号
- 它允许发送方发送多个分组而不需要等待确认,TCP的滑动窗口是以字节为单位的
- 每收到一个确认,发送方就把发送窗口向前滑动
4.3.3 停止等待ARQ和连续ARQ的对比
4.3.4 ARQ到底运行在那一层?
-
ARQ是一种可以在不可靠的数据通道上可靠地传输数据的方案,所以其实链路层和传输层都用了ARQ,并不专属某一层。
-
并不是一条连接只要有一层用了ARQ,它的上层的通信就是可靠的。因为ARQ只保证使用它的点到点是可靠的,比如数据链路层只保证你和你的路由器通信可靠,你的路由器到小区的路由器通信也可靠, 但是路由器本身会故障,会拥塞丢包,也就是点本身会产生问题。
-
所以需要在传输层或者应用层再加一层ARQ保障整条数据通道的可靠性。比如你自己写程序要在应用层通信,但传输层不用TCP想用UDP,也可以在你程序里用ARQ协来实现可靠性。
4.4 三次握手
TCP 三次握手,其实就是 TCP 应用在发送数据前,通过 TCP 协议跟通信对方协商好连接信息,建立起TCP的连接关系。
TCP连接并非是在通信设备两端之间建立信号通道,而是双方各自维护所需的状态,已达到TCP连接的效果。
4.4.1 三次握手的步骤
- 初始:最初客户端和服务器都是处于CLOSED(关闭)状态。服务器进程创建传输控制块(TCB),被动打开,进入LISTEN(监听)状态,时刻准备接收客户端的连接请求。
- 第一次握手:客户端进程创建传输控制块(TCB),然后客户端给服务器发送一个连接请求报文,指明同步位SYN=1,且客户端的初始化序列号(ISN,Initial Sequence Number)seq=x。此时客户端处于SYN-SENT(同步已发送)状态。SYN报文段不能携带数据,但是需要消耗掉一个序号。
- 第二次握手:服务器收到客户端的连接请求报文后,如果同意连接,则会向客户端发送确认报文。ACK=1,SYN=1,并且也指定了自己的初始化序列号(ISN)seq=y,同时ack=x+1(由于连接请求报文seq=x不携带数据,但消耗一个序号,所以ack=x+1),表示自己已经收到了客户端的SYN报文。此时服务器处于SYN_RCVD(同步已收到)状态。确认报文也不能携带数据,也是仍然消耗一个序号。
- 第三次握手:客户端收到确认报文后,还要向服务器发出确认。确认报文的ACK=1,seq=y+1,自己的序列号为seq=x+1。此时,客户端进入ESTABLISHED(已建立连接)状态。当服务器收到客户端的确认后也进入ESTABLISHED(已建立连接)状态。此时,双方就可以进行数据传输了。
4.4.2 三次握手的作用
- 确认收发双方的发送、接收能力是否都正常
- 第一次握手:客户端发,服务器收,这样服务器能够得出结论:客户端的发送能力、服务器的接收能力正常。
- 第二次握手:服务器发,客户端收,这样客户端能够得出结论:客户端的发送、接收能力与服务器的发送、接收能力是正常的。所以第二次握手后,客户端就进入ESTABLISHED状态。
- 第三次握手:此时服务器还不知道客户端的接收能力和服务器的发送能力是否正常。所以才有了第三次握手。客户端发,服务器收,这样服务器得出结论:客户端的发送、接收和服务器的发送、接收能力都是正常的。所以第三次握手后,服务器才进入ESTABLISHEDh状态。
- 指定自己的初始化序列号,为后面的可靠传送做准备
4.4.3 为什么需要最后一次握手
- 确认客户端和服务器双方的发送、接收能力是否均正常。如果只采用两次握手,服务器无法判断客户端的接收能力和服务器的发送能力是否正常
- 确认序列号的可靠同步。如果是两次握手,服务端无法确定客户端是否接收到了自己发送的初始序列号。如果第二次握手报文丢失,客户端无法知道服务端的初始序列号,那么TCP连接的可靠性无法保证。
- 阻止重复历史连接的初始化。客户端由于某种原因发送了两个不同序号的SYN报文,由于复杂的网络环境,有可能旧的SYN先到达服务器。采用三次握手,客户端在收到服务器发送的确认报文后,对比ack是对应旧的SYN报文还是新的SYN报文,如果是对应旧的,那么客户端就给服务器发送RST报文,直到正常的SYN到达服务器后才正常建立连接。
- 阻止超时请求建立连接浪费资源。如果一个连接请求在网络中传输的比较慢,超时后客户端会重新发送该连接请求,但是最后之前那个慢的连接请求最后还是到达了服务器。如果只采用两次握手的话,就会建立两个TCP连接,浪费资源。如果采用的是三次握手,就算是那之前失效的连接请求传送过来了,服务端接受到了那条失效请求并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。
4.4.4 如果已经建立了连接,但是客户端突然故障了怎么办
- TCP连接有一个保活计时器。
- 服务器每收到一次客户端的请求后都会重新复位这个计时器,通常时间设置为2小时。
- 如果2小时内,服务器一直未收到客户端的任何数据,服务器就会向客户端发送一个探测报文段,并且每隔75秒发送一次。
- 如果一连10个探测报文都没有反应,服务器就认为客户端出现故障,接着就会关闭连接。
4.4.5 三次握手时报文的初始化序号(ISN)是固定的吗
三次握手的一个重要功能是客户端和服务器交换ISN,以便让对方知道接下来接收数据的时候如何按序列号组装数据。
如果ISN是固定的,攻击者很容易就能猜出来后续的确认号,因此为了避免被攻击者猜到从而发送伪造的 RST报文,因此ISN是动态生成的。
4.4.6 什么是半连接队列
服务器第一次疏导客户端的连接请求后,就会从LISTEN状态进入SYN-RCVD状态,此时双方还没有完全建立连接。服务器会把这种状态下的请求连接放在一个队列里,这就是半连接队列。
当然还有全连接队列,就是已经完成三次握手的连接。
如果队列满了,就可能会出现丢包的现象。
关于SYN-ACK重传次数的问题:服务器发送完SYN-ACK报文,如果未收到客户端的确认报文,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传。如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同,一般会是指数增长,例如间隔时间为 1s, 2s, 4s, 8s, ….
4.4.7 三次握手过程中可以携带数据吗
第一次、第二次握手不可以携带数据,而第三次握手是可以携带数据的。
我们可以思考一个问题,假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据,疯狂着重复发 SYN 报文,这会让服务器花费大量的内存空间来缓存这些报文,这样服务器就更容易被攻击了。
对于第三次握手,此时客户端已经处于连接状态,他已经知道服务器的接收、发送能力是正常的了,所以可以携带数据是情理之中。
4.5 四次挥手
4.5.1 四次挥手的步骤
- 起初客户端和服务器都是处于ESTABLISHED状态。如果数据传输完毕,要释放连接,客户端主动关闭,服务器被动关闭。
- 客户端进程发出连接释放报文,并且停止发送数据。释放报文首部,FIN=1,序列号seq=u。此时客户端进入FIN-WAIT-1(终止等待1)状态。FIN报文即使不携带数据,也要消耗一个序号。
- 服务器收到连接释放报文后,发出确认报文。ACK=1,ack=u+1,并且带上自己的序号seq=v。此时服务器进入CLOSE-WAIT(关闭等待)状态。这时客户端向服务器方向的连接就释放了,处于半关闭状态,即客户端没有数据要发送了,但是服务器若发送数据,客户端依然接受。这个CLOSE-WAIT状态要持续一段时间,用于服务器把未发完的数据发送给客户端。
- 客户端收到服务器的确认请求后,客户端进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文。(在这之前还需要接收服务器发送的最后的数据)
- 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ACK=1,ack=u+1,并带上自己的序号seq=w(在半关闭状态时服务器可能又发送了数据,所以序号由u变为w)。此时服务器就进入LAST-ACK(最后确认)状态,等待客户端的确认。
- 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序号是seq=u+1。此时客户端进入了TIME-WAIT(时间等待)状态。此时TCP连接还没有释放,必须经过2*MSL(2倍的最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
- 服务器只要收到了客户端发出的确认,立即进入CLOSED状态,并撤销TCB。
- 可以看到,服务器结束TCP连接的时间要比客户端早一些。
4.5.2 为什么最后客户端要等待2*MSL
- 保证客户端发送的最后一个ACK报文能够达到服务器。因为这个ACK报文有可能丢失,站在服务器的角度,我已经发送了FIN+ACK的释放报文,但是客户端没有给出确认,那我就认为是客户端没有收到我发送的释放报文,于是我就重新发送一次这个释放报文。这样客户端就能在这个2MSL(客户端ACK到达服务器 + 服务器发送 FIN重传包,一来一回)时间内收到这个重传的报文,并给出确认,并且重启2MSL计时器。如果等待
2MSL
时间也没有收到服务器端的重传包FIN
,说明可以确认服务器已经收到客户端发送的ACK
。 - 防止类似于三次握手中提到的“已经失效的连接请求报文出现在本连接中”。客户端在发送完最后一个ACK报文后的2MSL时间内,就可以使本连接持续的时间内所产生的所有报文都从网络中消失,使得下一个新的连接中就不会出现旧连接的请求报文。(即避免本次连接中的请求进入下一次连接,场景:路由器缓存IP数据包)。
4.6 为什么建立连接是三次握手,而释放连接是四次挥手
建立连接的时候,服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
释放连接的时候,服务器收到客户端的FIN报文时,仅仅表示客户端不再发送数据了,但是客户端还可以接收数据,而自己也可能还有数据没有全部传送过去,所以服务器可以选择把所有数据全部发送给客户端之后再关闭连接,因此这时仅仅给客户端发送一个ACK报文表示自己已经收到了客户端发来的连接释放请求,但是还不能立即同意释放连接。所以当服务器把数据全部发送完毕后,给客户端发送FIN报文,表示同意现在关闭连接。
从上面可以看出,建立连接的时候,服务器把ACK和SYN报文放在一起发送给了客户端,表示同意建立连接。而在释放连接的时候,服务器先发送一个ACK报文告诉客户端已经收到了释放连接的请求,但是自己还未发完全部数据,所以暂时还不同意释放连接,等到数据全部发送完毕,服务器再发送一个FIN报文告诉客户端同意释放连接。确认和同意释放连接报文分开发送是四次挥手的原因。
4.7 流量控制
4.7.1 什么是流量控制
简单来说,流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。本质就是防止分组丢失。
接收端会维护一个处理窗口,就是接收端所能处理数据的能力。接收端将这个处理能力不断反馈给发送端,以此来让发送端调整发送的数据量的多少。
总结来说,对发送方发送速率的控制,我们称之为“流量控制”。
4.7.2 如何实现流量控制
由滑动窗口协议(连续ARQ协议)实现。该协议既保证了分组无差错、有序接收,也实现了流量控制。
主要的方式为,接收方返回给发送方的ACK报文中会包含自己的接收窗口大小rwnd,发送方利用接收窗口大小控制自己的发送窗口。
4.7.3 如何避免流量控制引发的死锁
死锁的发生场景:
接收方B给发送方A发送了rwnd=0的报文段后,发送方就知道不再向接收方发送数据了。不久后,如果B的接收缓存又有了一些空间,于是B向A重新发送一个含有非零rwnd的报文。然而这个报文段在传输过程中丢失了。发送方A一直在等待非零rwnd的报文,接收方B也一直在等待A发来的数据。如果没有其他措施,这种互相等待的死锁局面将一直持续下去。
如何解决死锁:
- 为了解决上述问题,TCP为每一个连接设有一个持续计时器。只要发送方A收到了接收方B的零窗口rwnd报文后,就启动持续计时器。
- 如果持续计时器的时间到期,发送方A就发送一个零窗口探测报文段(仅携带1个字节的数据),接收方B收到后就在确认这个探测报文段时给出现在的接收窗口值rwnd。
- 如果rwnd仍然是0,那么发送方就重置这个持续计时器。如果rwnd不是0,那么就可以打破死锁僵局。
4.8 拥塞控制
4.8.1 什么是拥塞控制
拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或者链路不至于过载。
4.8.2 为什么需要拥塞控制
当网络拥堵的时候,发送方的数据包可能一直未到达接收端,那么发送端误认为出现了丢包情况,于是就重传这个数据包,结果就造成了不仅浪费了信道资源,还使得网络更加拥塞。因此,需要进行拥塞控制。
4.8.3 如何知道网络的拥塞情况
A与B建立连接之后,A就可以向B发送数据了。然而这个时候A并不知道此时的网络拥塞情况如何,也就是说,A不知道一次性连续发送多少个数据包好,我们也把A一次性连续发送多少个数据包称之为拥塞窗口,用N代表此时拥塞窗口的大小。
如果线性增大拥塞窗口的大小,速率太慢了,如果指数增大拥塞窗口的大小,可能很快就到达瓶颈值了。所以采用“前期指数增长,到达阈值ssthresh后,线性增长”的策略。(注意这个阈值ssthresh并不是出现网络拥塞时的瓶颈值)
把前期指数增长阶段称之为“慢启动”,到达阈值后的线性增长阶段称之为“拥塞避免”。
这里的指数增长是因为,每个传输轮次中,发送方每收到一个对新报文段的确认,就使拥塞窗口+1,这样实现了相邻轮次间拥塞窗口的加倍增长。
传输轮次就是往返时间RTT,但RTT不是固定不变的。例如,拥塞窗口的大小为4个报文段,那么这时的往返时间RTT就是发送方连续发送4个报文段,并收到这4个报文段的确认,总共经历的时间。
4.8.4 到达瓶颈值了怎么办
在慢启动和拥塞避免过程中,最终肯定会出现超时,这时就认为网络出现拥塞了(把此拥塞窗口的瓶颈值用MAX表示),那么拥塞窗口就不能再继续增长了,并且需要进行缩小调整。
策略:出现网络拥塞时,拥塞窗口大小回到最初的状态:1,将阈值ssthresh=MAX/2
,继续进行慢启动和后续的拥塞避免。
4.8.5 超时一定是网络拥塞吗
超时是指发送方在指定时间内没有收到对数据包的确认,可能是出现了网络拥塞,也可能是因为某个数据包丢失或者损坏了,一直未收到对该数据包的确认,从而导致这个数据包的超时事件发生了。
为了防止这种情况,我们通过冗余ACK来处理的。
数据包是有序号的,如果A给B发送M1, M2, M3, M4, M5…N个数据包,如果B收到了M1, M2, M4…却始终没有收到M3,这个时候就会重复确认M2(最后一个连续数据包的序号)(称为“快重传”),意在告诉A M3还没收到,可能是丢失了。
当A连续收到了三个对M2的ACK,且M3的超时事件还没有发生。A就知道M3可能丢失了,这时A就不必等待M3设置的计时器到期,而是快速重传M3。并把阈值ssthresh=MAX/2(注意MAX是出现超时的时候的拥塞窗口瓶颈值,可能是拥塞,也可能是丢包,所以只要出现超时时的拥塞窗口值就是MAX,它并不是固定不变的,而是根据具体超时情况改变的)。但是这时并非把拥塞窗口N设置为1,而是让N=ssthresh,并以拥塞避免的方式(线性增长)增大拥塞窗口。这种情况称之为“快恢复”。
4.9 拥塞控制和流量控制的区别
- 拥塞控制是作用于网络的,它是防止过多的数据注入到网络中,避免出现网络负载过大的情况。
- 流量控制是作用于接受者的,它是控制发送方的发送速率从而使接收方来得及接收,防止分组丢失。
- 拥塞控制与网络的拥堵情况相关联,而流量控制与接收方的缓存状态相关联。
- 拥塞控制是一个全局性的过程,涉及到所有的主机、路由器,以及与降低网络传输性能有关的所有因素。
- 流量控制是点对点通信量的控制,是一个端到端的问题(接收端控制发送端)。