一、TCP重傳機制
保證所有的數(shù)據(jù)包都可以到達
注意:接收端給發(fā)送端的Ack只確認(rèn)最后一個連續(xù)包,如發(fā)五份數(shù)據(jù),收到1,2,于是回ack 3,然后收到4(注意此時3沒收到),TCP怎么辦?SeqNum和Ack以字節(jié)數(shù)為單位,ack時候,不能跳著確認(rèn),只能確認(rèn)最大連續(xù)收到包,不然,發(fā)送端就以為之前都收到
1、超時重傳機制
不回ack,死等3,發(fā)送方發(fā)現(xiàn)收不到3的ack超時后,會重傳3。接收方收到3后,ack 回 4—意味著3和4都收到
問題,要死等3,導(dǎo)致4和5即便收到,發(fā)送方也不知,因為沒收到Ack,可能重傳4和5
有兩種選擇:
? ?1)僅重傳timeout的包(3),省帶寬,慢
? ?2)重傳timeout后所有(3,4,5),快,可能會有無用功
2、快速重傳機制
于是,TCP引入Fast Retransmit 算法,以數(shù)據(jù)驅(qū)動重傳,不用等timeout再重傳。包沒連續(xù)到達,ack最后那個可能被丟了的包,發(fā)送方連續(xù)收3次相同ack,就重傳
如:發(fā)送方發(fā)1,2,3,4,5份數(shù)據(jù),1先到送,ack回2,2沒收到,3到達,ack還回2,4和5到了,還是ack回2,馬上重轉(zhuǎn)2。因為3,4,5都收到了,ack回6

3、SACK 方法(Selective Acknowledgment選擇承認(rèn))
在TCP頭里加SACK,SACK匯報收到的數(shù)據(jù)碎版,ACK還是Fast Retransmit的ACK
發(fā)送端根據(jù)回傳SACK,知道哪些數(shù)據(jù)到(優(yōu)化Fast Retransmit)。Linux通過tcp_sack打開這功能(默認(rèn)開)
注意1:接收方Reneging(有權(quán)把已回發(fā)送端SACK里的數(shù)據(jù)給丟了)。不鼓勵,因為復(fù)雜化,但要把內(nèi)存給更重要。所以,發(fā)送方不能完全依賴SACK,要依賴ACK,并維護Time-Out,如后續(xù)ACK沒增長,還要SACK東西重傳,ps:接收端不能把SACK包標(biāo)為Ack
注意2:SACK消費發(fā)送方資源,如攻擊者發(fā)?發(fā)送方一堆SACK選項,發(fā)送方重傳甚至遍歷已經(jīng)數(shù)據(jù),消耗資源

4、Duplicate SACK – 重復(fù)收到數(shù)據(jù)
又稱D-SACK,用SACK告訴發(fā)送方哪些被重復(fù)接收
(1)D-SACK使用了SACK的第一個段來做標(biāo)志:
如SACK第一段范圍,被 ACK 或 SACK第二個段? 所覆蓋,就是D-SACK
(2)示例一:ACK丟包
丟兩個ACK,1)發(fā)送端重傳第一個數(shù)據(jù)包(3000-3499),接收端發(fā)現(xiàn)重復(fù)收到,回SACK=3000-3500,2)ACK到4000,意味收到4000前所有數(shù)據(jù),3)這個SACK就是D-SACK——告訴發(fā)送端 收到重復(fù)數(shù)據(jù),發(fā)送端知道,數(shù)據(jù)包沒丟,丟ACK包

(3)示例二:網(wǎng)絡(luò)延誤
1)1000-1499網(wǎng)絡(luò)延誤,發(fā)送方沒收到ACK,2)后面到達三個包觸發(fā)“Fast Retransmit算法”,3)重傳時,延誤包到了,所以回SACK=1000-1500,ACK已到3000,4)SACK是D-SACK—標(biāo)識收到重復(fù)包。
發(fā)送端知道“Fast Retransmit算法”不是因為?發(fā)的/回應(yīng)的ACK包?丟了,因為網(wǎng)絡(luò)延時

(4)D-SACK好處:
1)讓發(fā)送方知道,發(fā)的包/回來ACK包 丟了
2)是不是自己timeout太小,導(dǎo)致重傳
3)先發(fā)的包后到(又稱reordering)
4)網(wǎng)絡(luò)上是不是復(fù)制我的包
知道這些可更好幫TCP了解網(wǎng)絡(luò)情況,從而做網(wǎng)絡(luò)流控。Linux的tcp_dsack默認(rèn)開啟這功能
http://www.52im.net/thread-513-1-1.html