TCP可靠傳輸,流量控制,擁塞控制,TCP的精華盡在于此
目錄
- 抓包過程以及TCP包首部
- 可靠傳輸
- 窗口概念引出接收窗口 rwnd 和發送窗口 cwnd
- 流量控制舉例來說明具體TCP流量控制過程
- 擁塞控制慢開始和擁塞避免算法快重傳和快恢復算法
- 流量控制和擁塞控制的區別
抓包過程以及TCP包首部
使用了 Wireshark 進行抓包,用兩個最常用的 curl 和 ping 命令來演示抓包情況,開啟抓包。
- ## 先訪問我自己的網站首頁
- curl https://zengzhiqin.kuaizhan.com
- ## 再查看我自己網站的地址
- ping https://zengzhiqin.kuaizhan.com
Wireshark根據 ping 命令得到的地址進行條件過濾,得到上面兩個命令所得到的包,主要有 TCP(https基于tcp協議)協議和 ICMP(ping命令是基于 ICMP 協議)協議的包,如下圖所示:

抓包分析

TCP首部數據一一對應

TCP頭部
可靠傳輸
TCP 實現可靠傳輸的四種實現方法:
- 校驗
- 序號
- 確認
- 重傳
第1,2兩種機制,在我公眾號另外一篇有詳細講解,這里我主要講述第3,4種。
可靠傳輸目的: 就是要讓發送方發送的所有數據,接收方都能完整,按序收到。
正如宮本武藏的口頭禪“排好隊,一個一個來”一樣,使用最笨的方法來解決最難的問題,既然你要可靠那么就一個一個確認,只要你沒告訴我你收到了,那么我就一直重發。
可靠傳輸的工作原理:停止等待協議

可靠與不可靠解決方式
我分為了四張圖,豎線代表的是時間軸,RTT代表數據包發過去然后確認包發回來的往返時間,分別是”無差錯你好我好大家好的情況下“,”發送超時或者失敗“情況下,”確認超時“和”確認丟失“的情況下來分析的。通過這種確認重傳機制,TCP就可以實現可靠傳輸,也就是第3,4點的實現方式。需要知道的一點是,重傳這個動作是發送方自發行為,并不需要接收方通知它進行重傳。
窗口概念引出
上面的方法,確實不錯哈,用了最簡單的方法解決了可靠傳輸這個問題,可是網絡時時刻刻那么忙,我等你一來一回的確認宮本武藏一個大招跳出去估計是一節一節的落地了,黃花菜都涼了。
上述停止等待協議最大的問題是信道利用率太低了。

停止等待傳輸
RTT時間是由網絡狀況決定拯救不了,T2一般也是固定的,由公式可看出,想要提高信道利用率只能從 T1 下手。

流水線傳輸
發送方可以連續發送多個包,不用每次都停下來等待確認再繼續發,將上面這些的連續發送的包用一個窗口來包含起來即TCP窗口的由來,如下圖:

滑動窗口
既然你發送方為了不一個一個包發可以有窗口技術,那么我接收方肯定也不甘落后得學起來啊,即不進行一個一個確認,轉而累積確認。

接收方累積確認方式
接收窗口 rwnd 和發送窗口 cwnd
此處涉及到二個窗口:
接收窗口receiver window(即rwnd),是接收方根據自己的承受能力設置的接收緩存值大小,反映了接收方的接收能力,來做流量控制。
擁塞窗口congestion window(即cwnd),是發送方根據網絡擁塞程度設置的網絡窗口值,發送窗口=min(rwnd,cwnd)即是接收窗口和擁塞窗口的最小值,來做擁塞控制。
窗口數據結構如下:

窗口數據結構
其實看似這么高深的東西,一步步想過來竟是如此簡單,感嘆一句”啊,聰明的人類“(調皮一下哈哈哈)。
流量控制
上面說到了通過窗口可以增大信道的利用率,然后就是窗口的大小怎么設置,設置多大,窗口還可以用來做什么?
發送方如果發的過快,那么接收方就會來不及接受,就會丟包,這肯定不行啊,萬一別人給我發了很多紅包丟一個我都不想噠~

分段傳輸
流量控制目的:讓發送方根據網絡狀況動態的調整發送頻率,好讓接收方來得及接收。
TCP利用滑動窗口機制實現流量控制。發送方的發送窗口是動態變化的,取決于接收方返回的報文段的窗口大小,可能是數據報文段也可能是確認報文,因為TCP包首部都有窗口信息,還是這張圖再看一下窗口數據:

舉例來說明具體TCP流量控制過程
A主機向B主機發送數據,建立連接的時候 B 告訴 A:”大哥,我的rwnd=400byte“,假設每個報文段都是100byte,初始序號是1,三次流量控制溝通過程如下:

舉例來說明具體TCP流量控制過程
這張圖,最后 rwnd=0 了,這種情況持續到接收端騰出了新的接收緩存之后 B會主動給 A發送他的新的 rwnd,0窗口通知的時候 A 就會一直等待接收方新的 rwnd 通知,為了防止新的 rwnd 丟失了,之前的文章很多都分析過這種情況,為了解決包超時收不到確認設置了等待一段時間就重傳,四次揮手過程設置了最后需要等待 2MSL 時間發送端才關閉,這些時間都是通過設置計時器來計時,都是為了解決包丟失了造成死鎖。同樣這里為了解決新的 rwnd 丟失了造成 A 死鎖發送端只要收到了0窗口通知就會啟動計時器,若時間到了就會重新發送一個0窗口探測報文,接收方再回復現在的接收窗口。
瘋狂試探
擁塞控制
我家小區網絡最好的時候是晚上3-6點,上午10-12點,下午3-5點,這些時間段我玩王者最暢快,晚上8-11點網絡高峰時段每次卡一下回過神我就站在了泉水(真的好開心)。
試想一下原本網絡就不好,然后你還一次性向網絡倒那么多數據包,大家都別過去了都超時,然后超時時間到了又都重發,惡性循環下去使得原本就不富裕的網絡更加雪上加霜,因此 TCP 你要自己學聰明,進行擁塞控制。 擁塞控制的目的就是防止過多的數據注入到網絡中,網絡堵塞使得包一直到不了接收端。

擁塞控制起到的作用
擁塞控制算法有四種:
- 慢開始
- 擁塞避免
- 快重傳
- 快恢復
慢開始和擁塞避免算法

慢開始和擁塞避免算法
一個傳輸輪次指的是發送了一批報文段并且收到了確認的時間 RTT。
慢開始是指數增長,一直試探網絡狀況如果健康就一直指數增長。到了ssthresh值的時候,這是慢開始輪限值,開始線性增長,一直增長到網絡擁塞的話,跳崖式降低一夜回到解放前,從1開始,將新的ssthresh值調低為原來擁塞時候的一半又開始指數增長,就這樣動態的變化。
快重傳和快恢復算法

快重傳和快恢復算法
從圖可以看到這個算法前面和慢開始擁塞避免算法是一致的,主要是調整了跳崖式降低發送速率這個地方,這樣從0開始效率太低了,如果是男女朋友間在發送微信豈不是被折磨的心癢癢。
擁塞窗口cwnd每次指數增長一次都是在收到了確認報文的情況下增長的,比如A發送1,23,4,5,6這些報文段,2丟失了,1345都收到了那么每次345收到都會給A發送確認1收到了的確認報文讓他發2(這個地方上一篇有提到),這種算法就是在2的超時計時器到期之前收到了三個確認之后就馬上重傳2,接收方都催著要了哥,后面三個確認包都到了說明網絡厚愛好的嘛就是你迷路了,因此進行快速重傳還是將新的ssthresh值調低為原來擁塞時候的一半又開始指數增長,現在一般是用這種,上面那種方法猶豫效率太低了被淘汰了。
流量控制和擁塞控制的區別
流量控制是點到點的問題,一對一,如果接收方的數據來不及接收那么就能直接找到發送方這個罪魁禍首,主要是因為接收方來不及接受發送方的數據;
擁塞控制是多對一,一個接收方 面對多個發送方出現了網絡擁堵,接收方找不到具體的發送方,主要是因為網絡發生了堵塞發送方數據遲遲到不了接收方。
簡單理解,擁塞控制是路上堵車,流量控制是停車場停車車位不夠。
這篇內容陸陸續續寫了好幾天了,感覺概念性的東西很多,我已經盡量再用聊天式的輕松語氣來寫了。北京今天下雨了,五道口兩旁的樹木長得郁郁蔥蔥,抬頭看見樹葉將天空撕成了碎片,耳機里一直在循環毛不易低沉性感聲線唱著的”一路山程“,我就這樣撐著傘走在這個都市的心臟上,一路憧憬著未來。