TCP可靠性传输

相信大家都熟知TCP协议作为一种可靠传输协议,但它是如何确保传输的可靠性呢?

要实现可靠性传输,需要考虑许多因素,比如数据的损坏、丢失、重复以及分片顺序混乱等问题。如果不能解决这些问题,就无法实现可靠传输。

因此,TCP采用了序列号、确认应答、重发控制、连接管理和窗口控制等机制来实现可靠性传输。

在本文中,我们将重点介绍TCP的滑动窗口、流量控制和拥塞控制。重传机制将在下一章节单独讲解。

流量控制

流量控制实际上是生产者和消费者之间微妙关系的一个具体体现。你可能在工作中或者面试中经常遇到这种考察场景。如果生产者的生产能力大大超过消费者的消费能力,就会导致队列无限增长。更严重的情况是,你可能知道当RabbitMQ消息堆积过多时,会导致整个MQ服务器性能下降。TCP也是类似的道理,如果不加以控制,过多的消息都被放到网络中,消费者已经超过了其能力范围,而生产者仍在重复发送,这会大大影响网络传输性能。

为了解决这种现象,TCP提供了一种机制,让发送方根据接收方的实际接收能力来控制发送的数据量,这就是所谓的流量控制。接收方维护一个接收窗口,而发送方维护一个发送窗口。需要注意的是,这些窗口只针对单个TCP连接,而不是所有连接共享一个窗口。

TCP通过使用一个接收窗口的变量来提供流量控制。接收窗口给发送方一个指示,告诉它还有多少可用的缓存空间。发送端根据接收端的实际接受能力来控制发送的数据量。

接收端主机会通知发送端主机自己可以接收数据的大小,发送端会发送不超过这个限度的数据。这个大小限度就是窗口大小,你还记得TCP首部吗?有一个接收窗口字段,它用于指示接收方能够或愿意接收的字节数量。

发送端主机会定期发送一个窗口探测包,用于探测接收端主机是否还能够接受数据。当接收端的缓冲区面临数据溢出的风险时,窗口大小的值也会相应地被设置为一个更小的值,通知发送端控制数据发送量。

以下是一个流量控制示意图:

为了确保接收端主机能够及时处理数据,发送端主机会根据接收端主机的窗口大小进行流量控制。这样可以防止发送端主机一次发送过大的数据导致接收端主机无法处理。

如上图所示,假设主机B的缓冲区已经满了,在接收到报文段2000-2999之后,它不得不暂停接收数据。为了解决这个问题,主机A会发送窗口探测包,这个包非常小,只有一个字节。主机B会根据接收缓冲区的情况更新接收窗口大小,并发送窗口更新通知给主机A。然后主机A可以继续发送报文段。

在上述发送过程中,窗口更新通知有可能会丢失。一旦丢失,发送端就不会继续发送数据。为了避免这种情况发生,窗口探测包会被随机发送,以确保通知的可靠传输。

拥塞控制

在介绍拥塞控制之前,我们需要了解除了接收窗口和发送窗口之外,还有一个拥塞窗口,它主要用于解决发送方以什么速度开始发送数据给接收窗口的问题。因此,拥塞窗口也是由TCP发送方进行维护的。我们需要一个算法来决定发送多少数据是合适的,因为发送数据过少或过多都不理想,所以就有了拥塞窗口的概念。

在之前的流量控制中,我们避免的是发送方的数据填满接收方的缓存,但是我们并不知道网络中发生了什么情况。通常情况下,计算机网络处于一个共享的环境中。因此,可能会因为其他主机之间的通信而导致网络拥堵。

当网络出现拥堵时,如果继续发送大量数据包,可能会导致数据包的延迟和丢失等问题。此时,TCP会重传数据,但是重传会增加网络的负担,导致更大的延迟和更多的丢包。这种情况会进入恶性循环,并不断放大。

因此,TCP不能忽略网络上发生的情况。当网络发生拥塞时,TCP会自我牺牲,降低发送的数据量。

因此,拥塞控制就应运而生,其目的是避免发送方的数据填满整个网络。为了调节发送方应该发送的数据量,所以TCP定义了一个叫做拥塞窗口的概念。拥塞控制的算法会根据网络的拥塞程度来调整拥塞窗口的大小,从而控制发送方的数据量。

什么是拥塞窗口?和发送窗口有什么关系呢?

拥塞窗口(Congestion Window)是发送方维护的一个状态变量,它决定了发送方可以发送的数据量。拥塞窗口会根据网络的拥塞程度动态变化。

发送窗口(Sending Window)是发送方和接收方之间约定的一个窗口大小,表示接收方可以接收的数据量。拥塞窗口和发送窗口有关系,发送窗口的值通常等于拥塞窗口和接收窗口中的最小值,即swnd = min(cwnd, rwnd)。

拥塞窗口cwnd的变化规则如下:

如果网络中没有出现拥塞,即没有发生超时重传,拥塞窗口会增大;

如果网络中出现了拥塞,拥塞窗口会减小。

发送方通过观察是否在规定时间内收到ACK确认报文来判断网络是否出现了拥塞。如果发送方在规定时间内没有收到ACK确认报文,就认为网络出现了拥塞。

除了拥塞窗口,下⾯我们就该聊⼀下 TCP 的拥塞控制算法(TCP congestion control algorithm) 了。TCP 拥塞控制算法主要包含三个部分:

  • 慢启动(Slow Start):初始时,拥塞窗口cwnd的值比较小,发送方以指数增加的方式增大拥塞窗口,以快速适应网络的容量。
  • 拥塞避免(Congestion Avoidance):拥塞窗口超过一定阈值后,发送方以线性增加的方式增大拥塞窗口,以减缓拥塞窗口的增长速度,避免过载网络。
  • 快速恢复(Fast Recovery):如果发生拥塞,发送方将拥塞窗口减半,并进入快速恢复状态,通过接收到的重复ACK来确定网络恢复的位置,然后继续增加拥塞窗口。

慢启动

当一条TCP连接建立时,拥塞窗口cwnd的初始值会设为一个MSS(最大报文段长度)的较小值。这样,初始的发送速率大约是MSS/RTT(往返时间)字节/秒。实际可用带宽通常比MSS/RTT大得多,因此TCP希望找到最佳的发送速率,可以通过慢启动的方式来实现。

在慢启动过程中,拥塞窗口cwnd的值会初始化为1个MSS,并且每次传输的报文段确认后,cwnd的值会增加一个MSS,即cwnd的值会变为2个MSS。之后,每成功传输一个报文段,cwnd的值就会翻倍,依此类推。具体的增长过程如下图所示。

然而,发送速率不可能一直增长,增长总有结束的时候。那么,何时结束发送速率的增长呢?慢启动通常会使用以下几种方式来结束发送速率的增长。

第一种方式是在慢启动的发送过程中出现丢包的情况。当发生丢包时,TCP会将发送方的拥塞窗口cwnd设置为1,并重新开始慢启动的过程。此时,引入了一个慢启动阈值ssthresh的概念,它的初始值就是产生丢包的cwnd的值的一半。也就是说,当检测到拥塞时,ssthresh的值就是窗口值的一半。

第二种方式是直接和慢启动阈值ssthresh的值相关联。因为当检测到拥塞时,ssthresh的值就是窗口值的一半,那么当cwnd大于ssthresh时,每次翻番都可能会出现丢包。所以,最好的方式就是将cwnd的值设为ssthresh,这样TCP就会转为拥塞控制模式,结束慢启动。

慢启动结束的最后⼀种⽅式就是如果检测到 3 个冗余 ACK,TCP 就会执⾏⼀种快速重传并进⼊恢复状态。(如果不清楚为什么会有三次同样的ACK报文,在重传机制中会单独讲解)

拥塞避免

当TCP进入拥塞控制状态后,cwnd的值会被设为拥塞阈值ssthresh的一半。这意味着无法每次收到报文段后都将cwnd的值翻倍。相反,采用了一种相对保守的方式,即每次传输完成后,只将cwnd的值增加一个MSS(最大报文段长度)。例如,即使收到了10个报文段的确认,但cwnd的值只会增加一个MSS。这是一种线性增长模式,它也有一个增长上限。当出现丢包时,cwnd的值将变为一个MSS,ssthresh的值将设为cwnd的一半;或者当收到3个冗余的ACK响应时,也会停止MSS的增长。如果在将cwnd的值减半后仍然收到3个冗余ACK,那么ssthresh的值将记录为cwnd值的一半,并进入快速恢复状态。

快速恢复

在快速恢复(Fast Recovery)状态中,对于每个收到的冗余ACK(即不是按顺序到达的ACK),拥塞窗口cwnd的值会增加一个MSS。这是为了利用网络中已经传输成功的报文段,尽可能地提高传输效率。

当丢失的报文段的一个ACK到达时,TCP会降低cwnd的值,然后进入拥塞避免状态。这是为了控制拥塞窗口的大小,避免继续加重网络拥塞。

如果在拥塞控制状态后出现超时,说明网络状况变得更加严重,TCP会从拥塞避免状态迁移到慢启动状态。此时,拥塞窗口cwnd的值被设置为1个MSS(最大报文段长度),而慢启动阈值ssthresh的值被设置为cwnd的一半。这样做的目的是为了在网络恢复后,重新逐渐增加拥塞窗口的大小,以平衡传输速率和网络拥塞程度。

总结

TCP协议作为一种可靠传输协议,通过序列号、确认应答、重发控制、连接管理和窗口控制等机制来实现可靠性传输。其中,流量控制机制通过发送方根据接收方的实际接收能力来控制发送的数据量,避免了网络拥堵和性能下降的问题。而拥塞控制机制则通过调节发送方的数据发送量,避免了网络拥塞的发生。拥塞窗口和发送窗口的概念相互关联,通过动态调整拥塞窗口的大小来控制发送方的数据量。慢启动、拥塞避免和快速恢复是TCP拥塞控制算法的三个主要部分,通过不同的策略来调节拥塞窗口的大小,以适应网络的容量和拥塞程度。

在下一章节中,我们将详细讲解TCP的重传机制。重传机制是TCP实现可靠传输的重要组成部分,通过对丢失、损坏或延迟的数据进行重传,确保数据的可靠性传输。重传机制的实现原理和策略将在下一章节中进行详细的介绍和解析。敬请期待!

TCP协议的秘密武器:流量控制与拥塞控制的更多相关文章

  1. TCP协议的滑动窗口协议以及流量控制

    参考资料 http://blog.chinaunix.net/uid-26275986-id-4109679.html http://network.51cto.com/art/201501/4640 ...

  2. TCP的流量控制与拥塞控制小结

    概述 为了提高信道的利用率TCP协议不使用停止等待协议,而是使用连续ARQ协议,意思就是可以连续发出若干个分组然后等待确认,而不是发送一个分组就停止并等待该分组的确认.其中TCP的流量控制与拥塞控制是 ...

  3. TCP基础知识(三)重传、流量控制、拥塞控制

    TCP详解(3):重传.流量控制.拥塞控制…… 数据传输 在TCP的数据传送状态,很多重要的机制保证了TCP的可靠性和强壮性.它们包括:使用序号,对收到的TCP报文段进行排序以及检测重复的数据:使用校 ...

  4. TCP的可靠传输(依赖流量控制、拥塞控制、连续ARQ)

    TCP可靠性表现在它向应用层提供的数据是无差错,有序,无丢失,即递交的和发送的数据是一样的. 可靠性依赖于流量控制.拥塞控制.连续ARQ等技术 <TCP/IP详解>中的“分组”是不是就是报 ...

  5. 运输层7——TCP的流量控制和拥塞控制

    目录 1. TCP的流量控制 2. TCP的拥塞控制 写在前面:本文章是针对<计算机网络第七版>的学习笔记 运输层1--运输层协议概述 运输层2--用户数据报协议UDP 运输层3--传输控 ...

  6. TCP 的三次握手和四次挥手,TCP 的流量控制和拥塞控制

    70.TCP协议的三次握手与四次挥手70.1.TCP报文结构   1.源端口号:表示发送端端口号,字段长为16位.  2.目标端口号:表示接收端口号,字段长为16位.  3.序列号:表示发送数据的位置 ...

  7. 【图解】你还在为 TCP 重传、滑动窗口、流量控制、拥塞控制发愁吗?看完图解就不愁了

    每日一句英语学习,每天进步一点点: 前言 前一篇「硬不硬你说了算!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题」得到了很多读者的认可,在此特别感谢你们的认可,大家都暖暖的. 来了,今 ...

  8. TCP 重传、滑动窗⼝、流量控制、拥塞控制

    重传机制 TCP 会在以下两种情况发⽣超时重传: 数据包丢失 确认应答丢失 重传超时 重传超时是TCP协议保证数据可靠性的另一个重要机制,其原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果 ...

  9. TCP流量控制与拥塞控制

    为了更好地对传输层进行拥塞控制,因特网建议标准定义了以下四种算法:慢启动.拥塞避免.快重传和快恢复. 1 接收窗口rwnd与拥塞窗口cwnd 发送方在确定发送报文段的速率时,既要根据接收方的接收能力, ...

  10. TCP/IP笔记 三.运输层(2)——TCP 流量控制与拥塞控制

    TCP 的流量控制与拥塞控制可以说是一体的.流量控制是通过滑动窗口实现的,拥塞避免主要包含以下2个内容: (1)慢开始,拥塞避免 (2)快重传,快恢复 1.流量控制——滑动窗口 TCP采用大小可变的滑 ...

随机推荐

  1. 深入理解注解驱动配置与XML配置的融合与区别

    摘要:本文旨在深入探讨Spring框架的注解驱动配置与XML配置,揭示两者之间的相似性与差异. 本文分享自华为云社区<Spring高手之路2--深入理解注解驱动配置与XML配置的融合与区别> ...

  2. STL-stack(ACM)

    1.没有.clear()操作,需要手动pop() 重构函数(默认) stack<int> a; 基础操作 a.push() // 入栈 a.pop() // 弹出栈顶元素 a.empty( ...

  3. 前端学习C语言 - 函数和关键字

    函数和关键字 本篇主要介绍:自定义函数.宏函数.字符串处理函数和关键字. 自定义函数 基本用法 实现一个 add() 函数.请看示例: #include <stdio.h> // 自定义函 ...

  4. 如何刷新 DNS 缓存 (macOS, Linux, Windows)

    如何刷新 DNS 缓存 (macOS, Linux, Windows) Unix Linux Windows 如何刷新 DNS 缓存 (macOS, FreeBSD, RHEL, CentOS, De ...

  5. AuthenticationException异常无法被全局异常捕获的解决办法

    我们可以先看一下为什么不能被捕获? 很明显JwtFilter的祖宗是Fliter,而我们自己定义的全局异常处理器@RestControllerAdvice 这个注解是 @ControllerAdvic ...

  6. 从数据库中读取数据并写入到Excle电子表格之2

     //CC_AutoId, CC_LoginId, CC_LoginPassword, CC_UserName, CC_ErrorTimes, CC_LockDateTime, CC_TestInt ...

  7. axios详解以及完整封装方法

    """ 一.axios是什么 Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中. 它是 isomorphic 的(即同一套代码可以运行 ...

  8. 现代C++(Modern C++)基本用法实践:N、其他零散的常用特性

    概述 这一篇简单介绍一些其他的比较实用的特性,如果读者想了解现代C++的全部特性,参考:cpp reference 其他特性 预置和弃置函数default&delete 在 C++11 中引入 ...

  9. Java stream流使用

    1.使用filter()过滤List //查找身高在1.8米及以上的学生 List<StudentInfo> boys = studentList.stream().filter(s-&g ...

  10. C# HttpClient请求gzip

    //设置HttpClientHandler的AutomaticDecompression var handler = new HttpClientHandler() { AutomaticDecomp ...