TCP 如何處理失敗重傳呢?


1  網絡協議背景概念

4層網絡傳輸是基於udp基於端口

7層網絡協議傳輸是基於tcp基於端口(tcp的復雜度很高很高..),並在tcp之上添加了會話層表示層應用層

upd協議面向報文,tcp協議 面上字節流。

 

啥是面向字節流呢?

 

2  TCP傳輸通信過程

tcp面向字節流,udp面向報文。那tcp的字節流是怎樣的呢?

tcp是點到點的通信,建立tcp鏈接的兩個端點,傳輸的數據不是報文,是一段數據中的一部分,並不知道一次讀的數據是多少和發送次數。

數據交給tcp層,由tcp決定一次發送多少數據,判斷條件有很多,發送窗口、擁塞窗口、路徑上的最大傳輸單元(MTU),輸出隊列數據總量等。

 

如圖在tcp發送數據之前,應用程序和tcp協議之間有一個tcp緩存隊列,這個隊列不固定字節大小,tcp要發送的數據也不固定字節大小,

tcp是去發送數據的一部分字節流,

並在這個傳輸中一直單向的進行。 ???????

所以在網絡傳輸中可以看到的是數據片段,然后是一組一組的數據交付給接收方。

 

3  傳輸報錯重傳機制

如果發送方發送 1 2 3 4 接收方只收到 1 2 回復確認 ack 3,然后發送方發來了 4,不能回復確認ack 5,因為不能跳躍確認。

於是,采用重傳機制,有2種:

3.1  超時重傳

發送方不知道3 4 5 的接收情況,接收方一直在等 3,這中方式會有比較嚴重的問題。

發送方有兩種選擇:

  a ,  默認 3 發送失敗,重新發送3 

  b ,默認 3 4 5 發送失敗,重傳 3 4 5 

a的方式,只傳 3可能會慢,b的方式傳 3 4 5 很快但是占用帶寬,timeout也可能很長,這兩個都不是最后的方法。

3.2  快速重傳

tcp還有一種 快速重傳 的算法,Fast-Retransmit,是以數據驅動重傳,不是timeout時間驅動。

怎么是以數據驅動呢?

就是 如果只收到 1 2 ,回復ack 3 ,隨后收到了 4 5 但是還沒收到 3, 4 5的ack也回復 3 3,這樣發送方會收到3個一樣的ack,會知道傳輸出了問題

這就是大部分tcp數據驅動重傳機制(什么?大部分tcp,總共是有幾個版本的..)。

這種方式還不是最好的,只是解決了timeout的問題,回傳的個數還是沒解決,比如一次發了20條,就不知道是哪3個發的ack了,需要回傳這20條。。

3.3  sack 重傳

選擇性重傳,Selective Acknowledgement(sack),tcp的頭會多一個SACK,快速重傳的ACK還在。

sack只回復已經到達的碎片,這樣發送端就能准確知道是重傳那部分字節流。在Linux可以用tcp_sack這個字段開啟這個功能,2.4版之后的Linux默認開啟。

 

參考:https://tools.ietf.org/html/rfc2018  https://www.jianshu.com/p/69695f332a71

 

遺留問題

tcp重傳還有一些問題,sack也不能完全相信:

如果有接收端會將數據保存直到失敗的分組重傳,就會有接受方內存擁擠把收到的數據丟棄了,可能有。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM