TCP的错误恢复我是我们定位、诊断、并最终修复网络高延迟的最好工具。
1.TCP重传
重传数据包是TCP最基本的错误恢复特性之一,它被设计用来对付数据包丢失。
数据包丢失可能有很多原因,包括出故障的应用程序、流量负载沉重的路由器,或者临时性的服务中断。数据包层次上的移动速度非常快,而且数据包丢失通常是暂时的,因此TCP能否检测到数据包丢失并从中恢复显得至关重要。
决定是否有必要重传数据包的主要机制叫做重传计时器。这个计时器负责维护一个叫重传超时(Retransmission timeout RTO)的值。每当使用TCP传输一个数据包时,就启动重传计时器。当收到这个数据包的ACK时,计时器停止。从发送数据包到接收ACK确认之间的时间被称为往返时间(Round-trip time RTT),将若干个这样的时间平均下来,可算出最终的RTO值。
在最终算出RTO之前,传输操作系统将一直依赖于默认配置的RTT值。此项设定于主机间的初始通信,并基于接收到的数据包RTT进行调整,以形成真正的RTO。
一旦RTO确定下来,重传定时器就被用于每个传输的数据包,以确定数据包是否丢失。
当数据包被发送出去,但接收方没有发送TCP ACK数据包时,传输主机就假设原来的数据包丢失了,并重传它。重传之后,RTO值翻倍;如果在到达极限值之前一直没有接收到ACK数据包,那将发生另一次重传。如果下一次重传还是没有收到ACK,RTO值将翻倍。每次重传,RTO值都将翻倍,这个过程会持续到收到一个ACK数据包,或者发送方达到配置的最大重传次数为止。(最大重传次数取决于传输操作系统上的配置,默认情况下,Windows主机最多重传5次,在部分Linux主机则默认最多重传15次,在操作系统中都是可以配置的。)如果发生重传,在wireshark中可以看到retransmission包。
2.TCP重复确认和快速重传
当接收方收到乱序数据包时,就发送重复的TCP ACK数据包。TCP在其头部使用序号和确认号字段,以确保数据被可靠接收并以发送顺序重组。
接收数据的序号+接收数据的字节数=发出的确认号
返回到发送方的确认号实际上就是接收方期待下次接收的数据包序号。
序号使数据接收方检测数据包丢失成为可能。当接收方追踪正在接收的序号时,如果遇到不合顺序的序号,它就知道数据包丢失了。
当接收方收到一个预料之外的序号时,它假设有一个数据包在传输中丢失了。为了正确地重组数据,接收方必须要得到丢失的数据包,因此它重新发送一个包含丢失数据包序号的ACK数据包,以使发送方重传该数据包。
当发送方收到3个来自接收方的重复ACK时,它假设这个数据包确实在传输中丢失了,并立刻发送一个快速重传。一旦触发快速重传,其他所有正在传输的数据包都要靠边,直到把快速重传数据包发送出去为止。(在wireshark数据包中可以看到This is a TCP duplicate ack,而发送方快速重传时,数据包中可以看到This frame is a fast retransmission)
3.TCP流量控制
重传和重复ACK都是TCP反应性的功能,被设计用来从数据包丢失中恢复。如果TCP没有包含某些形式的用于预防数据包丢失的前瞻性功能,它将是一个糟糕的协议,幸好它做到了。
TCP实现了滑动窗口机制,用于检测何时发生了数据包丢失,并调整数据传输速率加以避免。滑动窗口机制用用数据接收方的接收窗口来控制数据流。接收窗口是数据接收方指定的值,存储在TCP头部中(以字节为单位),它告诉发送设备自己希望在TCP缓冲空间中存储多少数据。发送方一次只能发送window size域指定的数据量。为了传输更多的数据,接收方必须发送确认,以告知之前的数据已经接收到了。
当一台繁忙的服务器处理来自多个客户端的数据包时,服务器可能会缓慢地清空缓冲区,腾不出空间来接收新数据。如果没有流量控制,这将导致数据包丢失和数据损坏。幸好,当服务器太繁忙,以致不能以接收窗口宣告的速率处理数据时,它可以调整接收窗口的大小。它通过减小向发送方返回ACK数据包的TCP头部窗口大小值,达到这个目的。
4.用零窗口通知停止数据流
服务器可以发送一个数据包,指明窗口大小是0。当客户端收到这个数据包时,它会停止所有数据传输,但仍通过传输“保活数据包”保持与服务器的连接。客户端周期性地发送保活数据包,以检查服务器接收窗口的状态。一旦服务器能再次处理数据,它会响应一个非0窗口以恢复通信。
5.从TCP错误控制和流量控制中学到的
1)重传数据包:发生重传是因为客户端检测到服务器没有接收到它发送的数据。因此,你能否看到重传取决于你在分析的通信的哪一端。如果你从服务捕获数据,并且它确实没有接收到客户端发送、重传的数据包,那你将蒙在鼓里,因为你看不到重传的数据包。如果你怀疑服务器端受到了数据包丢失的影响,你应该考虑在客户端那边捕获流量以观察是否有重传数据包。
2)重复ACK数据包:当接收到乱序数据包时才触发重复ACK。例如,如果服务器只接收到了第一个和第三个数据包,就会发送一个重复ACK以引发第二个数据包的快速重传。
3)滑动窗口与服务器接收、处理数据的故障直接相关。服务器的某些问题可以直接导致窗口大小减少或达到0窗口状态。
版权声明:本文为博主原创文章,未经博主允许不得转载。