TCP主要提供了检验和、序列号/确认应答、超时重传、最大消息长度、拥塞控制等方法实现了数据的可靠性传输!
一、检验和
通过检验和的方式,接收端可以检测出来数据是否有差错和异常,假如有差错就会直接丢弃TCP 段,重新发送。TCP在计算检验和时,会在TCP首部加上一个12字节的伪首部。检验和总共计算3 部分:TCP首部、TCP数据、TCP伪首部;
二、序列号/确认应答
发送端每次发送数据时,TCP就给每个数据包分配一个序列号并且在一个特定的时间内等待接收端对分配的这个序列号进行确认,如果发送端在一个特定时间内没有收到接收端的确认,则发送端会重传此数据包。接收端利用序列号对接收的数据进行确认,以便检测对方发送的数据是否有丢失或者乱序等,接收端一旦收到已经顺序化的数据,它就将这些数据按正确的顺序重组成数据流并传递到高层进行处理。
上述过程中,只要发送端有一个包传输,接收端没有回应确认包(ACK包),发送端就会认为数据丢包,然后进行重发。或者接收端的应答包,发送端没有收到也会重发数据。这就可以保证数据的完整性。
三、超时重传
TCP可靠性中最重要的一个机制是处理数据超时和重传。TCP协议要求在发送端每发送一个报文段,就启动一个定时器并等待确认信息;接收端成功接收新数据后返回确认信息。若在定时器超时前数据未能被确认,TCP就认为报文段中的数据已丢失或损坏,需要对报文段中的数据重新组织和重传。
我们知道,一来一回的时间总是差不多的,都会有一个类似于平均值的概念。比如发送一个包到接 收端收到这个包一共是0.5s,然后接收端回发一个确认包给发送端也要0.5s,这样的两个时间就是 RTT(往返时间)。然后可能由于网络原因的问题,时间会有偏差,称为抖动(方差)。
所以,超时重传的时间大概是比往返时间+抖动值还要稍大的时间。
注意:在重发的过程中,假如一个包经过多次的重发也没有收到对端的确认包,那么就会认为接收端异常,强制关闭连接。并且通知应用通信异常强行终止。
四、最大消息长度
在建立TCP连接的时候,双方约定一个最大的长度(MSS)作为发送的单位,重传的时候也是以这个单位来进行重传。理想的情况下是该长度的数据刚好不被网络层分块。
五、拥塞控制
滑动窗口控制解决了两台主机之间因传送速率而可能引起的丢包问题,在一方面保证了TCP数据传送的可靠性。然而如果网络非常拥堵,此时再发送数据就会加重网络负担,那么发送的数据段很可能超过了最大生存时间也没有到达接收方,就会产生丢包问题。为此TCP引入慢启动机制,先发出少量数据,就像探路一样,先摸清当前的网络拥堵状态后,再决定按照多大的速度传送数据。
发送开始时定义拥塞窗口大小为1;每次收到一个ACK应答,拥塞窗口加1;而在每次发送数据时,发送窗口取拥塞窗口与接送段接收窗口最小者。
慢启动:在启动初期以指数增长方式增长;设置一个慢启动的阈值,当以指数增长达到阈值时就停 止指数增长,按照线性增长方式增加至拥塞窗口;线性增长达到网络拥塞时立即把拥塞窗口置回 1,进行新一轮的“慢启动”,同时新一轮的阈值变为原来的一半。
拥塞控制算法主要有:慢启动、拥塞避免、快重传和快恢复;
1、慢启动
通常在一条TCP连接开始时,cwnd 被设置为 1 个 MSS(最大报文段),也即 cwnd = 1 该阶段,每当TCP发送方将发送窗口的数据发送完,并顺利接收到所有的确认后,就会将拥塞窗口大小翻倍,也即慢启动阶段,cwnd 以指数形式增长,如下图所示;注意这里忽略了接收窗口的影响,
拥塞窗口会一直增长直到到达慢开始门限 ssthresh,开始执行拥塞避免算法。
2、拥塞避免
该阶段的拥塞窗口变为线性增长,每次 cwnd + 1,也即每次增加一个 MSS;
随着拥塞窗口的增加,发送速率不断提高,当TCP遇到分组超时重传时,即认为发生了网络拥塞,此时将更新 拥塞窗口阈值 为当前拥塞窗口阈值的一半,下图中是更新为 24 的一半即 12 更新 cwnd 的值为1然后继续执行慢启动——拥塞避免,如下图所示;
如果TCP发送方接收到连续的3个重复确认,则认为是正常的网络包丢失,而不是网络拥塞造成的(这正是快重传算法的功劳)重传丢失的分组执行快恢复算法;
3、快重传
所谓的快重传算法,就是让发送方尽快重传,而不是等待计时器超时再重传;
(1)要求接收方不要等待自己发送数据时才捎带确认,而是要立即发送确认;
(2)即使是失序的报文段,也要立即发送对已收到的报文段的重复确认;
(3)发送方一旦收到3个连续的重复确认就认为发生数据丢包,就将相应的报文段立即重传,而不是等待该报文的重传计时器超时再重传;
4、快恢复
如果发送方收到了3个重复确认,就执行快恢复;
然后将快开始门限(慢启动阈值)和拥塞窗口阈值都设置为原来的一半,然后执行慢启动——拥塞避免;