TCP是一种巨复杂的协议,本篇文章旨在简单说明一些数据传输过程中常见的问题,对于涉及的算法目前并不会详细阐述(主要是个人能力原因)。
数据重传
TCP提供两种重传的机制,一种是基于时间的超时重传,一种是基于接收端反馈消息的快速重传。相比之下前者占用更少的网络带宽,但是效率很低。而后者则相反。下面我们来具体看一下这两种机制的实现方式。
-
超时重传
顾名思义,如果发送端等待接收端发送的ACK超过了TCP所设置的RTO,那么此时发送端便会重传刚发的数据包。一般而言,TCP会对数据包的超时重传非常重视,当发生这种情况时,TCP会降低当前发送端数据的发送速率以达到对该事件的快速响应。我们先来看一个例子:假设发送端发来序号标记为 1 2 3 的三个数据包,但是此时接收端只收到了数据包 1 3 这个时候接收端就走到了人生的十字路口,它可以选择不发ACK,死等数据包 2。但是数据包3 可能 因为超时面临着被重传的命运。
-
快速重传
与超时重传不同的是快速重传不会等待计时器变为超时,如果发现乱序、或者是丢失的数据包便会立即ACK,一旦发送端收到的重复ACK数目超过重复ACK阈值(一般来说为3),便会诱发快速重传机制。我们先来看一个例子:假设发送端发来序号标记为 **1 2 3 4 ** 的四个数据包,但是此时接收端只收到了数据包 1 3,此时数据包出现了乱序,接收端立即ACK 2,请求发送端发送数据包 2 ,这时数据包 4 也到达了接收端,接收端还是会立即ACK2。当数据包2 到达且数据包 3 4 并未超时,此时接收端会回复 ACK 5,否则当其他的数据包到达但是数据包2 未到达时时接收端便会一直ACK 2。
数据包的乱序和重复
TCP会将自己的数据报传递给IP层,但是IP层并不提供解决数据包重复、丢失和乱序问题的功能。它只负责规划主机之间具体的IP路径。TCP是一种可靠的字节流协议,所以它绝不会将次序混乱的数据段交给上层应用程序,所以TCP的实现就会考虑各种细节问题。
-
乱序
前面也谈到了,数据包会因为IP层所规划的路由链路的不同导致数据包的接收顺序与发送顺序会有所不同。另外因为TCP是一种全双工的协议,乱序可能发生在正向链路,也可能发生在反向链路,这两种不同的情况给TCP带来的影响也会略有差异。- 正向链路乱序:
此时TCP会无法判断是数据包丢失还是乱序,因为丢包和乱序都会导致接收端收到次序混乱的数据包,造成接收端的数据空洞。TCP会将这种情况暂定为数据包的乱序,因为乱序是时间问题(可能是数据包的迟到),而丢包则意味着重传。当TCP意识到包出现乱序的情况时,会立即ACK,该ACK的TSER部分包含的TSEV值会记录当前接收端收到有序报文段的时刻。这会使得数据包的RTT样本值增大,进一步导致RTO时间延长。这对TCP来说无疑是有益的,因为TCP有充分的时间判断数据包到底是失序还是丢了来防止不必要的数据重传。当然严重的乱序则会让发送端以为是丢包一旦重复的ACK超过TCP的阈值,便会触发超时重传机制,以及时解决这种问题。 - 反向链路(ACK)乱序:
顾名思义,如果发生这种情况,就会导致发送端窗口快速前移,这回导致发送端出现不必要的流量突发,影响网络带宽。
- 正向链路乱序:
-
数据包重复
对于数据包的重复,TCP的做法难免有些简单粗暴。首先我们知道每个数据报经由传输层的数据都会被打上相应的头,一般情况下,在固定20字节的TCP的头部中,有一个 4 字节的序列号段来表示数据在字节流中的偏移,对于接收端而言,该字段可以帮助自己直接将重复的数据包扔掉或者是对数据包进行重新组装,进而传递给上层。
都说一图胜千言,但是我实在想不到除了那几个协议头外该放哪些图,但是所说的这些内容与协议头又感觉关系不大所以索性一张图不放显得语言更加纯真些,如果你觉得内容很水,好吧,我承认它确实挺水的。。。。