聊聊TCP傳輸的滑動窗口協議的演進

寫這篇文章前,我有些肺腑之言想感謝一下我的微信好友“風大”。 是他給了我信心,原來沒有很難的技術,只要你肯努力總能趕上其他人。 後來關注他的博客後,發現他盡然覺得弄懂hashmap的 最好辦法是自己實現一個hashmap。一開始我也是不懂爲什麼要這樣,後來發現讀懂hashmap之後,再自己實現的時候,剛好可以讀懂hashmap中那些設計巧妙的地方,發現自己與大師的差距。最後我也總結了一個學習方法:
先弄懂一個技術怎麼樣,再考慮如果是自己去設計會是什麼樣子,一開始就算是抄,抄多了你就會自己寫了。
之前寫過一個springMVC的小輪子,後來看spring事務機制的時候 ,又寫了一個TransactionManage。
這些東西就像高冷的美女,只有你征服她時,你才能感受到她平凡而又不普通的一面。

開始進入話題:
兩個物理節點之間的網絡傳輸 如果不建立在7層網絡模型或者是5層網絡模型的基礎上,一定是不安全的。
那爲了讓網絡傳輸變得安全,所以5層網絡模型就每層都加了點東西,來給我們的網絡傳輸帶來一些保障。
沒有數據鏈路層,你怎麼把數據打包發出去呢?
沒有網絡層,你怎麼把你的愛說給你的女神呢?
沒有傳輸層,你怎麼保證你的女神就能收到你的愛呢?
沒有應用層,你女神怎麼知道你按什麼協議來發,他按什麼協議來接呢?HTTP 還是 FTP?

好的,今天我們重點來談談,傳輸層怎麼讓女神收到你的愛。一分不多,一分不少。

在網絡傳輸的過程中,經常會出現丟包,重複包,發錯了,發的順序不對等各種各樣的問題。
在傳輸層中使用的協議是 TCP/IP協議。
TCP協議 維持着 發送方 and 接收方 的緩衝區、 雙方商定包的重傳機制。接收方如何來ack 發送方發過來的包。

首先我們看看 如果生活中的兩個人發消息是怎麼發的,然後映射到網絡上:
這裏寫圖片描述

發送方發一個包1,接收方就確認一個包1,這樣看起來,邏輯上並沒有問題。
不會出現丟包呀,發重複包,發錯包了,發的順序不對的情況。
但是,問題來了,一個數據包的大小並不大,你一來我一回的,就導致了這個方案,發送消息的吞吐量上不去。如果你瞭解一些操作系統,多線程方便的知識,或者看過我之前關於cpu處理能力及redis 爲什麼是單線程的文章,
你一定知道,對於硬盤,還有網絡這種“慢速通道”,頻繁的多次IO絕不是一個好的方案,是可以將多次請求放到一個buff中,然後統一由這個buff 把多個消息拼在一起發送過去的。

所以改進的方案就來了,我可以將多個消息放在一起再發送過去,然後對方也可以一次性接受多個消息,只要順序是對的就可以了嘛,我們接着來看怎麼做。
改進方案1

滑動窗口協議就隨之產生了:

滑動窗口協議是傳輸層進行流控的一種措施,接收方通過通告發送方自己的窗口大小,從而控制發送方的發送速度,從而達到防止發送方發送速度過快而導致接收方接受不贏,導入數據丟失的問題。

關於滑動窗口協議可以使用搜索引擎或者上知乎瞭解:TCP協議的滑動窗口協議

看看滑動窗口協議是什麼樣子的:
這裏寫圖片描述

如果傳輸的過程中丟包了怎麼辦呢?
丟包
發送方丟包了,接收方不會回覆ack標識,同時又因爲接受方的滑動窗口大小是已經確定了的。所以並不會發送後面欄位的包。
那自然丟包了就要重發~ 重發的時候是什麼樣呢?
丟包重發

發送方發5號包,丟包時,滑動窗口協議會繼續的把6 7 號包發過去,但是接收方並沒有收到5號包,滑動窗口協議,爲了保證 傳輸的順序,接收方不會把 6 7號包的ack給發送回來,
只有在5號包重發後,並且接收方接收到了五號包的時候,接收方纔會將 5 6 7 號包的ack 再重新返回。
5 6 7號包的 ack 返回後, 滑動窗口又可以向右移動三位 去傳 12 13 14號包了。

這樣丟包的問題通過重發就解決了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章