1. 流量控制
我們都知道當網絡上數據流量超過網絡硬件負荷時就會出現網絡擁塞,就是我們平常遇到的網絡緩慢的現象。對應影響網絡速度的原因主要有網絡傳輸設備的性能和傳輸的數據多少,網絡傳輸設備包含發送接收主機、路由器、傳輸線路等。為了解決這個問題,TCP引入了流量控制,顧名思義,就是采用某種方法,控制收發端傳輸數據的速度,從而維持網絡數據傳輸的平衡。針對收發主機的處理速度,TCP使用滑動窗口來控制數據流量,減輕網絡壓力。
2. 滑動窗口
- 什么是滑動窗口
通過我們對TCP連接的建立和終止以及對TCP報文的學習,我們知道TCP連接是全雙工的,即可以雙向通信。TCP報文段首部中主要有序列號、確認號、標志字段、窗口等其他字段屬性,其中的窗口字段就是用來實現滑動窗口的。該字段表示發送該窗口字段信息的通信方為即將到來的數據預留的存儲空間大小,也就是它能接收的數據大小。另一方受到這個窗口值后,就會動態發送數據。窗口字段長度為16個字節,可以表示最大65535的值,即窗口最大為65535字節。
- 滑動窗口的工作原理
TCP連接中有發送方和接收方,發送方會維護一個發送窗口,接收方會維護一個接收窗口。
先來分析發送窗口,窗口結構如下。
在發送方一側會將要發送的數據組成一個隊列,依次發送隊列里的數據。隊列里面的數據包含幾個部分,有已經發送且已經確認的數據、已經發送但未確認的數據、即將發送的數據、現在還不能發送的數據這四個部分,其中的數字標號是數據序列號。在通信連接建立和每次傳遞數據時,收發兩方會交換各自窗口大小,表面自己能接收的數據大小,一般以字節為單位。上圖中提供的窗口即對方通告的窗口大小,可以看出為6個字節,同時窗口的左邊界為3,表明在序列號3及之前的數據已經發送並完成確認,則可以算出窗口的右邊界為9。同時我們可以知道有多少已經發送但未收到確認的數據,總共有3個字節,則發送邊界為6,所以最后我們可知可用窗口,即馬上能發送的數據序列號范圍為7-9。
隨着時間的推移,當我們收到已經發送的數據的ACK時,滑動窗口的左邊界就能右移,如果窗口大小未發生改變,那么窗口的右邊界也會右移,相當於整個窗口右移。其中在窗口的變化過程中有三個運動狀態:
- 關閉: 窗口左邊界右移。發生在收到已發送數據的ACK時。
- 打開: 窗口右邊界右移。發生在接收方已處理接收到的數據,使得接收方緩存變大,會給發送方通告新的變大的窗口值。
- 收縮: 窗口有邊界左移。發生再糊塗窗口中。
TCP報文的頭部中有兩個字段,一個是ACK確認號,一個是Window窗口值,在每次數據傳遞過程中,收發兩方都會傳遞這兩個字段,ACK表示對方已對小於ACK-1的報文進行確認,發送方能夠以此動態調整窗口的左邊界,Window窗口字段表示對方能接受的數據大小,發送方能夠據此動態調整窗口的右邊界。這樣就形成了窗口的向前滑動,所以形象地稱之為滑動窗口。
當ACK確認號增大,而窗口變小,即窗口的左右邊界靠攏,最后左右邊界相等,此時窗口大小為0,表示不能發送數據,稱之為0窗口。出現0窗口時,當接收端可接受空間變大時,會給發送端發送一個窗口更新ACK,使得發送端能夠繼續發送數據。但我們知道我們並未對ACK進行確認,那么ACK也有可能丟失。為了解決這個問題,發送端一般會采用TCP持續計時器見隔一段時間對接收端窗口進行探測,要求接收端返回自己的窗口大小,發送端隨時准備發送數據。
接收方也會維護一個窗口。保存已經接收到的數據狀態。
相比發送端維護的窗口,接收端維護的窗口就簡單很多了。只有已經接收並被確認,能接收數據的空間和不能接收的數據。當到達的數據序列號小於左邊界時,代表收到的是重復數據,因為這些數據已經被接收並已經被確認,接收端會選擇放棄這些數據。當收到的數據序列號大於右邊界時,代表該數據已超過了發送端處理范圍,也會被拋棄。只有收到的數據序列號再左邊界和右邊界之間時,才會接收保存,這樣窗口才會向前移動。