什么是重傳

好比我從淘寶買東西,商家通過快遞向我發(fā)送貨物, 但貨物可能在快遞途中弄丟了, 我反饋給商家貨物沒收到后, 商家給補(bǔ)發(fā)一個(gè)貨物, 這就是重傳。
商家怎么知道貨物丟了呢?可能是我的反饋,也可能是快遞公司的反饋,或是商家發(fā)現(xiàn)我沒確認(rèn)收貨。 這些方式就是ACK, SACK, RACK, NACK等報(bào)文了。怎么理解這些報(bào)文呢? 下面從三種傳輸方式來解釋重傳的原理和工作方式。
TCP的重傳機(jī)制
ACK: acknowledgement 應(yīng)答,響應(yīng)。 在TCP里的ACK是一種累積ACK, 當(dāng)前n個(gè)數(shù)據(jù)塊收到后, 接收端發(fā)送ACK n+1, 告知發(fā)送端前n個(gè)數(shù)據(jù)收到了,而不是發(fā)一塊數(shù)據(jù)給一個(gè)ACK響應(yīng)。
假如從A到B送d1, d2, d3,d4,d5,d6,d7七塊數(shù)據(jù):

其中d3, d4丟失了,
那么ACK就是這樣的:
- B收到d2后, ACK 3, 表明收到了d1, d2。
- B收到d5后, ACK 3, 因?yàn)闆]收到d3, 無法累積,還停留在游標(biāo)3。
- B收到d6, d7后, 還是ACK 3, 同上。
什么時(shí)候會(huì)重傳d3, d4呢?
-
超時(shí)重傳:
RTO
A每發(fā)送完一塊數(shù)據(jù)d后,會(huì)將其加入超時(shí)重傳隊(duì)列, 當(dāng)收到ACK 3后,將d1,d2從隊(duì)列移出, 當(dāng)d3 - d7的計(jì)時(shí)T到達(dá)后,就會(huì)開始對(duì)其進(jìn)行重傳。
快速重傳:
收到了3個(gè)ACK 3, A就可以判定d3沒收到了, 重發(fā)d3。
從這里可以發(fā)現(xiàn)快速重傳機(jī)制有個(gè)問題: 觸發(fā)了d3的快速重傳, 但d4還沒有重傳,d4要等到自己的T4 timeout到了或是三個(gè)ACK 4才重傳,顯然時(shí)延加大了, 有沒有好的解決辦法呢? 這就引入了SACK。
SACK: Selective Acknowledgement 選擇性的應(yīng)答。在TCK協(xié)議里的SACK就是接收放告知發(fā)送方收到了一些數(shù)據(jù)片段, 它是ACK的補(bǔ)充, 如上例, B通過ACK告知了A收到了d1, d2, 但沒告知A收到片段d5, d6,d7。

有了SACK, 就可以提前觸發(fā)d4的重傳了。
QUIC的重傳機(jī)制
QUIC的重傳機(jī)制同TCP的類似,同樣用到ACK, SACK, RTO。 但改進(jìn)了TCP重傳機(jī)制中的問題。
TCP重傳機(jī)制的問題:
-
重傳歧義: 由于重傳的包的序號(hào)沒有變更, 導(dǎo)到ACK響應(yīng)的不知是原始包還是重傳包。
重傳歧義
計(jì)算網(wǎng)絡(luò)的來回時(shí)延rtt就可能出錯(cuò), 如下圖所示: rtt = d3_t3 - d3_t1, 就錯(cuò)誤的將rtt變大了。
SNACK帶來的reneging問題, 即接收方發(fā)了很多SNACK, 且這些SNACK里攜帶了很多跳躍的應(yīng)答數(shù)據(jù),導(dǎo)致發(fā)送方大量的重傳計(jì)算,這種往往是一種攻擊手段。
webrtc的重傳機(jī)制
NACK: Negative Acknowledgement 消極應(yīng)答。所謂消極應(yīng)答, 就是接收端不反饋收到哪些數(shù)據(jù),而是反饋沒有收到哪些數(shù)據(jù)。

當(dāng)B收到d5后,通過對(duì)比序列號(hào),發(fā)現(xiàn)d3, d4沒收到, 那么發(fā)送NACK, 告知A, d3, d4丟失了, A就可以重傳d3, d4了。

