在 TCP 中,当发送端的数据到达接收主机时,接收端主机会返回一个确认应答消息,表示已收到消息。但在错综复杂的网络,并不一定能那么顺利能正常的数据传输,万一数据在传输过程中丢失了呢?TCP 针对数据包丢失的情况,会用重传机制解决。
常见的重传机制:
???????
在发送数据时,设定一个定时器,当超过指定的时间后,没有收到对方的?ACK
?确认应答报文,就会重发该数据,也就是我们常说的超时重传。
TCP 会在以下两种情况发生超时重传:
RTT
(Round-Trip Time 往返时延)RTO
?(Retransmission Timeout 超时重传时间)对于RTO
?「较长或较短」有两种超时时间不同的情况:
?
根据上述的两种情况,我们可以得知,超时重传时间 RTO 的值应该略大于报文往返 RTT 的值。
Linux 下,α = 0.125,β = 0.25, μ = 1,? = 4。
?
ps:如果超时重发的数据,再次超时的时候,又需要重传的时候,TCP 的策略是超时间隔加倍,也就是每当遇到一次超时重传的时候,都会将下一次超时时间间隔设为先前值的两倍。两次超时,就说明网络环境差,不宜频繁反复发送。
快速重传(Fast Retransmit)机制,它不以时间为驱动,而是以数据驱动重传。
快速重传的工作方式是当收到三个相同的 ACK 报文时,会在定时器过期之前,重传丢失的报文段。
重传的时候,是重传一个,还是重传所有的问题。(例如上图是只重传Seq2 ,还是Seq2 ,Seq3,Seq4,Seq5都重传)
如果只选择重传 Seq2 一个报文,那么重传的效率很低。因为对于丢失的 Seq3 报文,还得在后续收到三个重复的 ACK3 才能触发重传。
如果选择重传 Seq2 之后已发送的所有报文,虽然能同时重传已丢失的 Seq2 和 Seq3 报文,但是 Seq4、Seq5的报文是已经被接收过了,对于重传 Seq4 ~Seq5?折部分数据相当于做了一次无用功,浪费资源。
SACK
( Selective Acknowledgment),?选择性确认。
在 TCP 头部「选项」字段里加一个?SACK
?,它可以将已接受那部分的信息发送给[发送方],这样发送方就可以只重传丢失的数据。
发送方收到了三次同样的 ACK 确认报文,于是就会触发快速重发机制。并通过?SACK
?信息发现只有?200~299
?这段数据丢失,则重发时,就只选择了这个 TCP 段进行重复。
ps:如果要支持?SACK
,必须双方都要支持。在 Linux 下,可以通过?net.ipv4.tcp_sack
?参数打开这个功能(Linux 2.4 后默认打开)。
D-SACK 全称Duplicate SACK,其使用了 SACK 来告诉「发送方」有哪些数据被重复接收了。
D-SACK
。D-SACK
?有这么几个作用:
ps:在 Linux 下可以通过?net.ipv4.tcp_dsack
?参数开启/关闭这个功能(Linux 2.4 后默认打开)。