一、TCP重传机制
保证所有的数据包都可以到达
注意:接收端给发送端的Ack只确认最后一个连续包,如发五份数据,收到1,2,于是回ack 3,然后收到4(注意此时3没收到),TCP怎么办?SeqNum和Ack以字节数为单位,ack时候,不能跳着确认,只能确认最大连续收到包,不然,发送端就以为之前都收到
1、超时重传机制
不回ack,死等3,发送方发现收不到3的ack超时后,会重传3。接收方收到3后,ack 回 4—意味着3和4都收到
问题,要死等3,导致4和5即便收到,发送方也不知,因为没收到Ack,可能重传4和5
有两种选择:
1)仅重传timeout的包(3),省带宽,慢
2)重传timeout后所有(3,4,5),快,可能会有无用功
2、快速重传机制
于是,TCP引入Fast Retransmit 算法,以数据驱动重传,不用等timeout再重传。包没连续到达,ack最后那个可能被丢了的包,发送方连续收3次相同ack,就重传
如:发送方发1,2,3,4,5份数据,1先到送,ack回2,2没收到,3到达,ack还回2,4和5到了,还是ack回2,马上重转2。因为3,4,5都收到了,ack回6
3、SACK 方法(Selective Acknowledgment选择承认)
在TCP头里加SACK,SACK汇报收到的数据碎版,ACK还是Fast Retransmit的ACK
发送端根据回传SACK,知道哪些数据到(优化Fast Retransmit)。Linux通过tcp_sack打开这功能(默认开)
注意1:接收方Reneging(有权把已回发送端SACK里的数据给丢了)。不鼓励,因为复杂化,但要把内存给更重要。所以,发送方不能完全依赖SACK,要依赖ACK,并维护Time-Out,如后续ACK没增长,还要SACK东西重传,ps:接收端不能把SACK包标为Ack
注意2:SACK消费发送方资源,如攻击者发 发送方一堆SACK选项,发送方重传甚至遍历已经数据,消耗资源
4、Duplicate SACK – 重复收到数据
又称D-SACK,用SACK告诉发送方哪些被重复接收
(1)D-SACK使用了SACK的第一个段来做标志:
如SACK第一段范围,被 ACK 或 SACK第二个段 所覆盖,就是D-SACK
(2)示例一:ACK丢包
丢两个ACK,1)发送端重传第一个数据包(3000-3499),接收端发现重复收到,回SACK=3000-3500,2)ACK到4000,意味收到4000前所有数据,3)这个SACK就是D-SACK——告诉发送端 收到重复数据,发送端知道,数据包没丢,丢ACK包
(3)示例二:网络延误
1)1000-1499网络延误,发送方没收到ACK,2)后面到达三个包触发“Fast Retransmit算法”,3)重传时,延误包到了,所以回SACK=1000-1500,ACK已到3000,4)SACK是D-SACK—标识收到重复包。
发送端知道“Fast Retransmit算法”不是因为 发的/回应的ACK包 丢了,因为网络延时
(4)D-SACK好处:
1)让发送方知道,发的包/回来ACK包 丢了
2)是不是自己timeout太小,导致重传
3)先发的包后到(又称reordering)
4)网络上是不是复制我的包
知道这些可更好帮TCP了解网络情况,从而做网络流控。Linux的tcp_dsack默认开启这功能
http://www.52im.net/thread-513-1-1.html