Skip to content

TCP是如何实现可靠传输的

TCP (Transmission Control Protocol, 传输控制协议) 之所以能够实现“可靠传输”,是因为它设计了一套精密的、环环相扣的机制来应对网络中可能出现的各种问题,如数据包丢失、重复、乱序或损坏。

IP协议本身是“尽力而为”的,不保证数据能送达,而TCP正是在IP协议之上构建了一个可靠的通信层。其可靠性主要通过以下几个核心机制来实现:

序列号 (Sequence Numbers)

这是TCP实现有序传输和数据完整性检查的基础。

  • 工作原理: TCP在发送数据时,会将数据分割成一个个大小合适的报文段 (Segment)。它会为每个报文段中的第一个字节分配一个序列号。例如,第一个报文段的序列号是1,包含1000字节的数据,那么下一个报文段的序列号就会是1001。

  • 如何保证可靠性:

    • 解决乱序问题:网络传输中,后发的数据包可能先到。接收方可以根据序列号对接收到的报文段进行重新排序,从而恢复出原始的、有序的数据流。
    • 解决重复问题:如果接收方收到了两个序列号相同的报文段,它就知道其中一个是重复的,会直接丢弃重复的那个。

确认应答机制 (Acknowledgements, ACKs)

这个机制用来确认数据是否被对方成功接收。

  • 工作原理: 当接收方收到来自发送方的数据后,会发送一个确认(ACK)报文段作为回应。这个ACK报文中包含一个“确认号”,这个号码的数值是“接收方期望收到的下一个字节的序列号”。例如,接收方成功收到了序列号为1到1000的数据,它就会回复一个ACK,确认号为1001。

  • 如何保证可靠性:

    • 确认数据到达:发送方收到ACK后,就知道之前发送的数据已经被对方成功接收。这种一发一收的确认模式是可靠性的核心。这种累计确认的机制效率很高,确认了1001,就代表1001之前的所有数据都收到了。

超时重传 (Timeout and Retransmission)

当TCP发送一个数据段(Segment)后,它会启动一个计时器,并将该数据段放入重传队列。

  • 确认机制 (Acknowledgement - ACK):接收方在收到数据后会向发送方发送一个确认消息(ACK)。这个ACK消息包含下一个期望接收的字节的序列号。
  • 重传定时器 (Retransmission Timer):发送方为每个发送的数据段设置一个重传定时器。如果在定时器到期之前没有收到对应数据段的ACK,发送方就会认为该数据段丢失,并重新发送该数据段。
  • 动态调整RTO (Retransmission Timeout):重传超时时间(RTO)的设定至关重要。如果RTO太短,可能导致不必要的重传;如果RTO太长,会降低传输效率。TCP会根据网络状况(如往返时间RTT)动态地计算和调整RTO。
    • TCP通过测量发送数据到接收到ACK的往返时间(RTT)来估算网络的延迟。
    • 它会维护一个平滑的RTT估算值(SRTT)和一个平均偏差估算值,利用这些值来计算出更合适的RTO。
    • 在每次重传之后,RTO通常会指数级地增加,这被称为“指数退避”(Exponential Backoff),以应对持续的网络问题。
  • 快速重传 (Fast Retransmit):为了更及时地处理丢包,TCP还引入了快速重传机制。如果发送方收到三个或更多重复的ACK(Duplicate ACKs),它会立即重传丢失的数据段,而无需等待重传定时器超时。这通常表明某个数据段在传输过程中丢失,但后续的数据段已经到达接收方。

流量控制 (Flow Control)

流量控制是为了防止发送方发送数据过快,导致接收方的缓冲区溢出,从而造成数据丢失。TCP通过“滑动窗口协议”(Sliding Window Protocol)实现流量控制。

  • 接收窗口 (Receive Window - rwnd):接收方在其发送的每个ACK报文中,都会包含一个“接收窗口大小”(rwnd)字段。这个字段表示接收方当前能够接收的字节数量,也就是其缓冲区中剩余的可用空间。
  • 发送方的限制:发送方会根据接收方通告的接收窗口大小来调整其发送数据量,确保发送的数据不会超过接收方当前的处理能力和缓冲区容量。
  • 滑动窗口:发送方维护一个“发送窗口”,代表它可以在未收到ACK的情况下发送的数据量。随着数据的发送和ACK的接收,这个窗口会在序列号空间上向前“滑动”。
  • 零窗口 (Zero Window):如果接收方的缓冲区已满,它会通告一个零窗口大小。此时,发送方将停止发送数据,直到接收方通告一个非零的窗口大小,表示缓冲区有可用空间。为了避免死锁,TCP会使用一个“持久计时器”(Persist Timer),当接收方通告零窗口时,发送方会周期性地发送小探测报文(probe segment),以获取接收方最新的窗口大小信息。

拥塞控制 (Congestion Control)

拥塞控制是为了防止过多的数据注入到网络中,导致网络性能下降(如丢包、延迟增加),甚至出现“拥塞崩溃”(Congestive Collapse)。流量控制是点对点(发送方到接收方)的,而拥塞控制是全局的(考虑整个网络)。TCP拥塞控制主要通过四个阶段实现:慢启动、拥塞避免、快速重传和快速恢复。

  • 拥塞窗口 (Congestion Window - cwnd):除了接收窗口外,发送方还维护一个“拥塞窗口”(cwnd)。实际发送的数据量是接收窗口和拥塞窗口中的较小值。拥塞窗口由发送方根据网络拥塞情况动态调整。
  • 慢启动 (Slow Start)
    • 当TCP连接建立时,拥塞窗口初始化为一个较小的值(通常为1或2个TCP段)。
    • 每当发送方收到一个ACK,拥塞窗口就会指数级地增长。例如,初始发送1个段,收到ACK后发送2个段,再收到ACK后发送4个段,以此类推,呈指数增长。
    • 这个阶段会持续到拥塞窗口达到一个预设的“慢启动阈值”(ssthresh),或者检测到丢包。
  • 拥塞避免 (Congestion Avoidance)
    • 当拥塞窗口达到或超过慢启动阈值(ssthresh)后,TCP进入拥塞避免阶段。
    • 在这个阶段,拥塞窗口的增长变为线性。每当收到一个RTT内所有已发送数据的ACK时,拥塞窗口只增加一个TCP段的量。这种机制被称为“加法增大”(Additive Increase)。
    • 如果检测到丢包(通过超时或重复ACK),通常会假定网络发生了拥塞。
  • 拥塞检测与恢复
    • 超时触发:如果发生重传超时,这被认为是严重的拥塞迹象。TCP会将慢启动阈值(ssthresh)设置为当前拥塞窗口的一半,然后将拥塞窗口重置为初始的较小值,再次进入慢启动阶段。
    • 快速恢复 (Fast Recovery):当收到三个重复ACK时,这表明有丢包,但网络可能并未严重拥塞(因为还有后续数据到达)。
      • 此时,TCP将慢启动阈值(ssthresh)设置为当前拥塞窗口的一半。
      • 拥塞窗口减小到新的ssthresh值。
      • 然后,TCP进入快速恢复阶段,在每个收到重复ACK时,拥塞窗口会线性增加,直到收到新的ACK确认了所有之前丢失的数据。这避免了完全回到慢启动的低效率。这种机制被称为“乘法减小”(Multiplicative Decrease)。

校验和 (Checksum)

这个机制用来检测数据在传输过程中是否发生了损坏。

  • 工作原理: 发送方在发送数据前,会根据TCP头部和数据内容计算出一个16位的校验和值。接收方收到数据后,会用同样的方法进行计算。如果计算出的校验和与收到的不一致,就说明数据在传输过程中被篡改或损坏了。

  • 如何保证可靠性:

    • 保证数据完整性:如果接收方发现校验和不匹配,它会直接丢弃这个损坏的报文段,并且不会发送ACK。这样,发送方就会因为超时而重传这个报文段,确保了最终数据的正确性。