计算机网络笔记、面试八股(四)—— TCP连接
本章目录
- 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 拥塞控制和流量控制的区别
- 拥塞控制是作用于网络的,它是防止过多的数据注入到网络中,避免出现网络负载过大的情况。
- 流量控制是作用于接受者的,它是控制发送方的发送速率从而使接收方来得及接收,防止分组丢失。
- 拥塞控制与网络的拥堵情况相关联,而流量控制与接收方的缓存状态相关联。
- 拥塞控制是一个全局性的过程,涉及到所有的主机、路由器,以及与降低网络传输性能有关的所有因素。
- 流量控制是点对点通信量的控制,是一个端到端的问题(接收端控制发送端)。
相关文章:

计算机网络笔记、面试八股(四)—— TCP连接
本章目录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和连续AR…...

Centos7 安装jenkins java1.8版本
1. 首先安装好jdk1.8 2. 安装jenkins 命令:(可以在根目录,创建文件夹 mkdir home 然后在此文件夹下操作 cd /home) a 清华源,获取jenkins安装包 wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/redhat/jenkins-2.346-1.1.noarch.rp…...

【每日阅读】JS知识(三)
var声明提升 js是一个解释性语言类型,预解析就是在执行代码之前对代码进行通读 var关键字是,在内存中声明一个变量名 js在代码执行之前 会经历两个环节 解释代码 和执行代码 声明式函数 内存中 先声明一个变量名是函数 这个名代表的是函数 乘法表 // for…...

Vue(6)
文章目录1. 自定义指令1.1 函数式1.2 对象式1.3 自定义指令常见坑1.4 创建全局指令2. 生命周期2.1 引出生命周期2.2 分析生命周期2.3 总结3. 组件3.1 认识组件3.2 使用组件 (非单文件组件)3.3 全局组件3.4 组件的几个注意点3.5 组件的嵌套3.6 VueComponent 构造函数3.7 一个重要…...

Neo4j列表函数
使用列表 标量列表函数 size() 函数返回列表中的元素的数量 MATCH (p:Person)-[:ACTED_IN]->(m:Movie) WITH p, collect (m.title) AS MovieTitles WITH p, MovieTitles, size(MovieTitles) AS NumMovies WHERE NumMovies > 20 RETURN p.name AS Actor, NumMovies, Movie…...

55. 跳跃游戏
给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标。示例 1:输入:nums [2,3,1,1,4]输出:true解释:可以先跳 1 步&#…...

typedef在c语言中的作用
在 C 语言中,typedef 是一个非常有用的关键字,用于给数据类型定义一个新的名字。typedef 的作用有以下几个方面: 定义新类型名:typedef 可以定义一个新的数据类型名称,使得该类型名称可以在程序中使用。这样可以提高代…...

计算机网络体系结构及分层参考模型
文章目录一、分层设计思想的提出二、网络分层的必要性三、什么是计算机网络体系结构四、计算机网络参考模型OSI参考模型/五层参考模型/TCP/IP参考模型一、分层设计思想的提出 最早提出分层思想的是 ARPANET网。1969年11月,美国国防部开始建立一个命名为ARPANET的网络…...

LLVM程序分析与编译转换框架论文分享
LLVM 2004年论文原文 概述 本文描述了 LLVM(低级虚拟机),一种编译器框架,旨在通过在编译时、链接时、运行时,以及运行之间的空闲时间。 LLVM 以静态单一赋值 (SSA) 形式定义了一种通用的低级代码表示,具有…...

《程序员思维修炼》速读笔记
文章目录书籍信息概览绪论从新手到专家的历程认识大脑利用右脑调试大脑主动学习积累经验控制注意力超越专家图解书籍信息 书名:《程序员思维修炼(修订版)》 作者:[美] Andy Hunt 概览 绪论 再提“实用”关注情境所有人都关注这…...

【Hello Linux】进程概念
作者:小萌新 专栏:Linux 作者简介:大二学生 希望能和大家一起进步! 本篇博客简介:简单介绍下进程的概念 进程基本概念PCB 程序控制块task_struct是什么task_struct里面有什么查看进程通过系统目录查看进程通过ps指令查…...

Bunifu.UI.WinForms 6.0.2 Crack
Bunifu.UI.WinForms为 WinForms创建令人惊叹的UI Bunifu.UI.WinForms我们为您提供了现代化的快速用户界面控件。用于 WinForms C# 和 VB.NET 应用程序开发的完美 UI 工具 简单 Bunifu.UI.WinForms没有臃肿的特征。正是您构建令人惊叹的 WinForms 应用程序所需要的。只需拖放然…...

学习 Python 之 Pygame 开发魂斗罗(五)
学习 Python 之 Pygame 开发魂斗罗(五)继续编写魂斗罗1. 加载地图2. 修改角色尺寸和地面高度继续编写魂斗罗 在上次的博客学习 Python 之 Pygame 开发魂斗罗(四)中,我们完成了角色的移动和跳跃还有射击,由…...

LeetCode 104. 二叉树的最大深度
LeetCode 104. 二叉树的最大深度 难度:easy\color{Green}{easy}easy 题目描述 给定一个二叉树,找出其最大深度。 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 说明: 叶子节点是指没有子节点的节点。 示例: 给定二叉树 [3…...

pandas 中如何按行或列的值对数据排序?
在处理表格型数据时,常会用到排序,比如,按某一行或列的值对表格排序,要怎么做呢? 这就要用到 pandas 中的 sort_values() 函数。 一、 按列的值对数据排序 先来看最常见的情况。 1.按某一列的值对数据排序 以下面…...

「牛客网C」初学者入门训练BC139,BC158
🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️🔥专栏系列:线性代数,C初学者入门训练 🔥座右铭:“不要等到什么都没有了,才下定决心去做” 🚀🚀🚀大家觉不错…...

【深度学习】线性回归、逻辑回归、二分类,多分类等基础知识总结
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言1. 线性回归2、逻辑回归3. 单层神经元的缺陷&多层感知机softmax 多分类最后再来一个 二分类的例子前言 入行深度学习快2年了,是时间好好总结下基础知识了.现…...

【MySQL】调控 字符集
一、 MySQL 启动选项 & 系统变量 启动选项 是在程序启动时我们程序员传递的一些参数,而 系统变量 是影响服务器程序运行行为的变量 1.1 启动项 MySQL 客户端设置项包括: 允许连入的客户端数量 、 客户端与服务器的通信方式 、 表的默认存储引擎 、…...

FME+YOLOV7写DNF自动刷图脚本
目录 前言 一、难点分析 二、实现流程 1.DNF窗口位置获取 2.获取训练数据 3.数据标注 4.数据格式转换 5.数据训练 5.刷图逻辑编写 前言 这是一篇不务正业的研究,首先说明,这不是外挂!这不是外挂!这不是外挂!这只是用a…...

Java语法面试题
多线程锁 Synchronized:一次只能被一个线程占有ReadWriteLock:被多个线程持有,写锁只能被一个线程占有ReentrantLock:一个线程的多个流程能获取同一把锁,就是可重入锁,即在一个线程中可以被重复的获取自旋锁…...

location
目录 匹配的目标 格式 匹配符号: 优先级 要表达不匹配条件,则用 if 实现 例子:根目录的匹配最弱 例子:区分大小写 和 不区分大小写 例子:以根开头 和 不区分大小写 例子:等号 匹配的目标 ng…...

简述RBAC模型
RBAC(Role-Based Access Control)模型是一种常用的访问控制模型,用于管理和控制用户对系统资源的访问权限。RBAC模型通过将用户分配给角色,并授予角色相应的权限,来实现安全的资源访问管理。 在RBAC模型中,…...

倒计时2天:中国工程院院士谭建荣等嘉宾确认出席,“警务+”时代来临...
近日伴随公安部、科技部联合印发通知,部署推进科技兴警三年行动计划(2023-2025年),现代科技手段与警务工作相结合的方式,正式被定义为未来警务发展的新趋势。 21世纪以来,随着科技的不断发展和创新…...

Python蓝桥杯训练:基本数据结构 [哈希表]
Python蓝桥杯训练:基本数据结构 [哈希表] 文章目录Python蓝桥杯训练:基本数据结构 [哈希表]一、哈希表理论基础知识1、开放寻址法2、链式法二、有关哈希表的一些常见操作三、力扣上面一些有关哈希表的题目练习1、[有效的字母异位词](https://leetcode.cn…...

MacOS 配置 Fvm环境
系统环境:MacOS 13,M1芯片 1. 安装HomeBrew: /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" speed 2. 使用brew安装Fvm: brew tap leoafarias/fvm brew install fvm 3…...

Python小白入门- 01( 第一章,第1节) 介绍 Python 编程语言
1. 介绍 Python 编程语言 1.1 Python 是什么 Python 是一种高级的、解释型、面向对象的编程语言,具有简洁、易读、易写的语法特点。Python 由 Guido van Rossum 于 1989 年在荷兰创造,并于 1991 年正式发布。 Python 语言广泛应用于数据科学、Web 开发、人工智能、自动化测…...

高并发系统设计之缓存
本文已收录至Github,推荐阅读 👉 Java随想录 这篇文章来讲讲缓存。缓存是优化网站性能的第一手段,目的是让访问速度更快。 说起缓存,第一反应可能想到的就是Redis。目前比较好的方案是使用多级缓存,如CPU→Ll/L2/L3→…...

【N32WB03x SDK使用指南】
【N32WB03x SDK使用指南】1. 简介1.1 产品简介1.2 主要资源1.3 典型应用2. SDK/开发固件文件目录结构2.1 doc2.2 firmware2.3 middleware2.4 utilities2.5 projects Projects3. 项目配置与烧录3.1 编译环境安装3.2 固件支持包安装3.3 编译环境配置3.4 编译与下载3.5 BLE工程目录…...

pytest测试框架——pytest.ini用法
这里写目录标题一、pytest用法总结二、pytest.ini是什么三、改变运行规则pytest.inicheck_demo.py执行测试用例四、添加默认参数五、指定执行目录六、日志配置七、pytest插件分类八、pytest常用插件九、改变测试用例的执行顺序十、pytest并行与分布式执行十一、pytest内置插件h…...

KAFKA安装与配置(带Zookeeper)2023版
KAFKA安装与配置(带Zookeeper) 一、环境准备: Ubuntu 64位 22.04,三台 二、安装JDK1.8 下载JDK1.8,我这边用的版本是jdk1.8.0_2022、解压jdk tar -zxvf jdk1.8.0_202.tar.gz 3、在/usr/local创建java文件夹,并将解压的jdk移动到/usr/local/java sudo mv jdk1.8.0_202…...