欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > 重温TCP通信过程

重温TCP通信过程

2025/4/28 16:32:55 来源:https://blog.csdn.net/m0_60963435/article/details/147568179  浏览:    关键词:重温TCP通信过程

文章目录

    • 1. 慢启动
    • 2. 拥塞避免
  • 3. 快速重传和快速恢复

初识tcp报文

我们先来简单认识一下报文的格式,具体理解需要后面详细介绍

  1. 源端口和目的端口:顾名思义就是标识传输双方的信息
  2. 首部长度:指的是TCP报头的长度,换句话来说,我们需要用一个属性来描述报头的长度,就说明TCP的报头是变长的
  3. 选项:实际上这里翻译为"可选项"更加准确,这是TCP为了适应复杂的网络环境和更好的服务应用层而进行设计的,TCP选项部分最长可以达到40byte ,再加上TCP选项外的固定的20byte字节部分, TCP的最长头部可达60byte
  4. 序列号:在一个TCP连接中传输的字节流中的每一个字节都按顺序编号,该字段表示本报文所发送的数据的第一个字节的序号
  5. 确认号:表示期待收到对方下一个报文段的第一个数据字节的字段,例如当确认号为N,表示序列号N-1之前的所有数据都已全部接收到
  6. 窗口:通知发送端,接收端可接受的空间大小
  7. 校验和:发送端计算发送的TCP报文段的校验和,接收端对接收到的TCP报文段,验证其校验和,如果不一致,说明数据包在发送端和接受端之间传输的时候发生了变动,此时该TCP报文会被直接丢弃
  8. 保留位: TCP报头里,提前申请好的一块空间,这个空间暂时用不上,但是说不定以后就能够用的上(万一以后TCP要扩展一些新的功能,就可以用这个保留位来表示了)
  9. 6位标志位:他们中的一位或者多位可以同时设置为1,用于说明该报文性质,其中下面三个字段需要格外注意:
    1. ACK,仅当ACK为1的时候,确认号字段才有效,TCP规定,当连接建立之后,所有传输的报文都必须将ACK设置为1
    2. SYN,仅在三次握手建立TCP连接时有效,当SYN=1,ACK=0时,表明这是一个连接请求报文,若对方同意连接,则在响应报文中设置SYN=1 和 ACK = 1
    3. FIN,用来释放一个连接,当FIN=1时,表示此报文的发送方的数据已经发送完毕,并要求释放连接

三次握手建立连接

为了确保通信双方都能**确认对方的存在和可用性**,并且**数据能够被正确的传输和接收**,TCP要求通信双方建立一条可靠的通信连接

三次握手是TCP协议中用于建立可靠连接的过程:

  1. A向B发送一个SYN报文,请求建立连接

  1. B收到A的SYN报文后回复一个SYN + ACK的报文

  1. A收到B的SYN报文之后,回复一个ACK报文

  1. B接受到ACK报文之后,表示一个TCP连接就建立好了

如果对上面的建立连接过程不懂,可以看下面的例子:

那么此时就很容易发现,为什么一定要三次握手??两次行不行??

答案是否定的,因为只有经过最后一次交互,B才能知道对方的接受能力和自己的发送能力是没问题的

分段机制

TCP经过三次握手之后就能发送数据了,但是一般网络不能连续的传输任意长的数据,因此,发送方A将需要传输的消息分割成小快,按照顺序分别发送,这些小块就是数据包

B接受到数据报之后,经过校验和校验无误之后,开始将收到的数据包进行重新组装,还原成原始消息

但是可想而知,数据包组装需要安装分割前的顺序进行拼接,但是我们确不能保证B接受数据包的顺序和我们传输的顺序是一致的,因为在网络传输过程中会经过很多交换机和路由器的传输,而不同的设备传输速度,负载情况,网络拥堵等因素都会影响数据包的传输顺序

为了解决这个问题,TCP在数据包的头部定义了一个序列号的字段,用于对在一个TCP连接中传输的字节流中的每一个字节按顺序进行编号,就可以解决乱序的问题了

确认应答+超时重传机制

为了保证所有的数据包都能够正确接收,TCP引入了确认应答机制

B在接收到数据之后,会回复一个携带确认号的确认包,也就是ACK包,A接收到ACK报之后,再发送下一个数据包

如果结果一段等待时间之后,发送包无法知道数据包的情况,则可能出现以下的情况:

解决这个问题的一般方法是超时重传,A在发送数据包之后,不会一直等待,而是启动一个重传定时器,定时到期之后未收到数据包,就会认为数据包丢失了,从而重传数据包

滑动窗口机制

在上面确认应答机制的情况下,A只有当接收到B回复的ACK包之后,才能继续发送下一个数据包

在这种场景下,发送方大多数时间都是在等待接收方的ACK中,极大的影响了通信的效率

一种解决问题的方法就是滑动窗口,这种机制允许发送方连续发送多个数据包而无需等待

TCP使用一个称为发送窗口的变量,表示无需等待确认即可发送的数据包的数量

那么发送窗口的大小设置为多少才是合理的呢?

如果太小,那就和我们上面简单的确认应答机制没什么区别了

如果太大,接收方可能会来不及处理而丢失数据包,得不偿失

TCP使用滑动窗口的机制,要求接收方维护一个可处理的接收窗口,发送方根据接收窗口来调整发送窗口的大小,从而根据接收方的接受能力来动态控制流量

通信双方每次在发送数据时,都会在TCP报头中携带窗口的大小.表示自己当前的接收能力

前面我们说过为了保证所有数据包都被收到,要求每个数据包接收到之后都要返回一个ACK包

延时应答 +累计确认

在滑动窗口的场景下,如果每个数据包都要回复一个ACK包的话,过多的确认包会消耗网络资源,降低网络利用率

对于累计确认来说,就是如果接收方返回确认号为N的ACK包,则表明N之前但不包括N的数据包已经全部接收到了

而延迟确认指的是接收方在接收到数据包之后不立即回复,而是延迟等待一段时间,这样在延迟的时间内收到多个连续的包可以累计成一个ACK确认

通过这两种方式,减少了ACK包的数量,提高了网络利用率

快速重传机制

前面说过,接收方等待一定时间之后,如果未接收到ACK包,就会触发超时重传

但是还是需要等待一定时间,降低了传输效率

TCP引入了快速重传机制:当接收方连续收到三个相同的确认号的时候,就会触发快速重传,立即重传数据包,而不必等待超时时间

拥塞控制

滑动窗口只考了接收方的处理能力,发送端根据接收窗口的大小发送数据,而忽略了网络的负载情况

随着网络连接数量的增加,必然会造成网络拥堵,就可能引起大量的超时重传,形成恶性循环,造成整个网络不可用

因此要进行拥塞控制来避免这种情况的发生

拥塞控制的主要思路是防止过多数据注入网络,以避免网络出现负载过大,也就是要根据网络拥塞情况,对发送数据包的数据进行控制

TCP定义了一个拥塞窗口的变量,如果网络拥堵就减少拥塞窗口,畅通就增加拥塞窗口

我们前面说过,发送窗口的大小等于接收窗口的大小

现在引入拥塞窗口之后,发送窗口的大小就等于拥塞窗口和接收窗口中的最小值,这样就能有效控制网络的发送效率

其中Reno算法是当前应用最广泛的拥塞控制算法

主要包含慢启动、拥塞避免、快速重传、快速回复

1. 慢启动

刚接入网络的时候先发送少量数据包,探测网络情况,然后再一点点逐步提高发送包的数量

2. 拥塞避免

慢启动的指数级别增长不可能一直持续下去,当发生网络拥堵的时候,慢启动增长就会结束

同时TCP定义了一个慢启动阈值的变量,当拥塞窗口超过这个阈值,就会进入拥塞避免模式,结束指数级增长

假设我们这个阈值是8,当超过8之后,就会以1的数量级增加,以线性增长,这种线性增长的方式相对于指数增长的方式更加稳定,可以避免网络拥塞的发生

但是也不能一直增长,和慢启动一样,当发生网络拥堵的时候,拥塞窗口的增长就会结束

那么网络拥堵是怎么感知到的?? 同时拥塞窗口又怎么调整呢?

TCP是通过丢包来感知网络拥堵状态的

丢包可以分为两种

  1. 超时丢包

也就是经过一段等待时间之后,还没收到ACK包,这种情况说明网络拥堵比较严重,TCP会进入慢启动模式,并将慢启动阈值设置为出现丢包时候的拥塞窗口的一般,重新开始慢启动,后拥塞避免…

  1. 第二种是收到三次重复的ACK

此时就会认为之前发送的数据包丢失,这种情况下认为当前网络发生了轻微拥堵,此时拥塞窗口减小的幅度不会像超时丢包那么大,会执行快速重传和快速恢复算法

3. 快速重传和快速恢复

  1. 将慢启动阈值设置为当前拥塞窗口的一半,并重传丢失的数据包
  2. 将拥塞窗口设置为当前慢启动阈值加上3,这是因为,发送方收到了3个相同的ACK说明当前已经有三个数据包到达了接收端,网络的"在途数据量"减少了三个,此时将拥塞窗口加上3,就是适当将拥塞窗口尽可能的变大些
  3. 再次收到重复的ACK,将拥塞窗口增加1
  4. 当收到新的数据包的ACK的时候,将拥塞窗口设置为第一步设置的阈值的值,此时快速恢复结束,再次进入拥塞避免阶段

实际上第一次学我也是云里雾里的,这里有必要通过一个例子来解释一下我的理解:

  1. cwnd(拥塞窗口)=9,此时发送9个数据包(序号1-9)
  2. 假设5数据包丢失,但是报文6~9正常到达接收端
  3. 接收端每次接受到6~9的数据包,都会回复一个ACK=5,发送端连续收到了3个ACK
  4. 触发快速重传,立即重传丢失的报文5,同时更新阈值(ssthresh= cwnd / 2 = 4.5 = 4)
  5. 进入快速恢复阶段,设置cwnd = ssthresh+3 = 7,加3是因为,由于已经收到了3个重复的ACK,说明(6,7,8)报文已经成功到达了接收端,可以将窗口向上提3个大小,不会导致下降太多
  6. 在等待ACK=5的报文阶段,允许发送新的报文(10~13),此时又会收到连续的重复的ACK=5,此时每收到一个就将cwnd+1,原因和5一样
  7. 当收到新的ACK=6,说明网络恢复,此时重置窗口cwnd=4,退出快速回复,进入拥塞避免阶段,为什么要重新降低?? 我觉得有以下原因
    1. 快速恢复阶段通过临时增大窗口(**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">cwnd = ssthresh + 3</font>**)来维持数据传输,但此时网络可能仍处于敏感状态,若继续保持这个值,可能会导致拥塞循环
    2. 重置窗口后,TCP进入拥塞避免阶段,确保窗口增长更平滑,避免突然的流量激增。

四次挥手结束通信

TCP是全双工的,每个方向可以同时传递数据,因此每个方向需要单独的关闭
  1. A方发送FIN来终止这个方向上的传输,待对方确认(返回ACK)后进入半关闭状态(也就是说A此时还能接受B发送来的数据 ,因为只是A认为自己结束了,B可能还在发送)
  2. B发现自己数据发送完毕之后,发送给AFIN来终止传输,待A确定后(返回ACK)终断连接

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词