核心機制一:確認應答
實現讓發送方知道接受方是否收到數據
發送方發送了數據之后,接受方,一旦接收到了,就會給發送方返回一個"應答報文"告訴發送方"我已經收到了數據"
網絡上會出現"后發先至"的情況
為了解決上述問題,就引入了"序號和確認序號"對于數據的傳輸進行標識
TCP 是字節流傳輸的
序號和確認序號是針對"字節"進行編號的
一個 TCP 數據報,包含多個字節,如何體現所有編號呢?
編號是連續遞增的,要知道 TCP 載荷的第一個字節的編號是多少,后面的每一個字節的編號就都知道了
32 位序號和數據:填寫數據報部分的第一個字節編號幾就行了
同一個 TCP 連接,序號會連續累加,下一個數據報的序號在上一個數據報的最后一個的序號基礎上繼續遞增
確認序號只在應答報文中生效
確認序號根據收到的數據的最后一個字節的序號進行加一來進行填充
這一位為 1 ,確認序號字段就會有效負責是屬于"無效字段"
確認序號的含義:
1.所有 < 確認序號的數據,接收方已經收到了
2.發送方接下來應該是從確認序號的位置開始,繼續發送數據
這樣的規則,非常有用,會在后面的特性中,有所體會
確認應答,就是 TCP 實現可靠傳輸的,最關鍵機制之一
這個地方的長度有多少,就看你代碼是怎么寫的
確認應答,關鍵是,數據順利到達,通過 ack 告知發送方
實際傳輸中,很有可能丟包的
TCP 核心機制二:超時從傳
確認應答的重要補充,針對丟包的場景的
超時:發送方,判定是否出現丟包的條件
重傳:發現數據丟包,就在發一次(概率性問題)
假設一個數據包,傳輸過程中,丟包的概率大概是 10%(相當大的數字)
連續傳輸兩次,數據包至少一次到達對方的概率是多少?
1 - 10% * 10% => 99%
傳輸次數的增加,數據報到達對方的概率概率大幅度增加
計算機中,一般不喜歡"無限的等",最大等待時間"超時時間"
沒有收到 ack 有兩種情況~~
這種情況丟包之后重傳,理所當然的
B 已經收到過一份數據了接下來又重傳一次,B 這邊同樣的數據收到了兩份~~
TCP 協議已經處理上述情況
TCP 在接受到數據的時候,會在操作系統內核中維護一個"接受緩沖區"(內存空間)
如果又收到了同一個數據,此時就可以根據數據的序號來在接受緩沖器中進行"去重"
確保應用程序,在進行 read 操作的時候,讀到的數據不會出現重復
TCP 也會針對對收到的數據在接受緩沖器中進行從重新排序,數據傳輸可能出現"后發先至"
1 - 1000 先發的, 1001 - 2000 后發的
接受方先收到了 1001 - 2000,后收到了 1 - 1000
TCP 的處理方式是在 接受緩沖區里,針對收到的數據進行排序
應用程序讀到數據的時候,讀到的仍然是有效的數據
超時重傳的超時時間不是固定的,動態變化的
隨著超時重傳的進行,如果還是沒有收到 ack 仍然要繼續重傳,但是等待的超時時間會逐漸變長
通過重傳之后,大幅度提升數據到達對方的概率,但是重傳之后,還是沒有收到 ack,只能說明,當前網絡的丟包概率,遠遠不止 10%了,此時,網絡大概率出現了非常嚴重的故障了,再次頻繁重傳,非但不會解決問題,甚至可能會加重網絡的故障程度~~
沒指望重傳能成功,死馬當活馬醫
重傳次數 / 總的重傳時間是有上限的,到達上限,重傳還沒成功, tcp 連接就會被"重置"(重置涉及到"復位報文") => 單方面的斷開連接了.
RST 觸發了一個復位報文,意味著這個鏈接就不要了
單方面通知
"釋放鏈接"就相當于是刪除掉之前保存的對方的信息
超時重傳,TCP中,進行可靠傳輸的重要機制之一
是確認應答的補充
確認應答處理傳輸順利的情況,超時重傳處理丟包的情況
網絡上很多資料關于這里討論的是有問題的
"TCP 的可靠性是通過 三次握手 實現的"
實際上不是這樣的
三次握手只是在建立連接之初,涉及到的環節.一旦連接建立好了,后續就沒有 握手的事情了