TCP的滑動窗口是一個很重要的概念,也是很晦澀的一個知識點。下面就大概介紹下TCP滑動窗口為什麼出現?它是怎麼工作的的?
首先,要理解,client和server各自協議棧都有自己的buffer,應用層讀寫數據的源都是協議棧buffer裡。以接收端為例,應用程 序調用read()時,會從buffer裡移走數據到用戶空間,應用程序讀的速度越快(read(1024)必然比read(1)要快),那麼 buffer裡的內容消費的越快,buffer也會越空。那麼TCP就可以告訴client,我現在很閒,你可以發送更多的數據來。"更多"是多少?這就 說窗口,窗口就是量化接收端和服務端當前能處理數據的能力。
client和server端建立連接後,client會告訴server,自己的"接收窗口"大小(自己能接收多少的數據,受上面所說的 buffer影響),server端接收到client的"接收窗口"大小,就會變成server端自己的"發送窗口"大小。同樣的,server端告訴 client自己的"接收窗口"大小,就會變成客戶端的"發送窗口"大小。
為了理解TCP的窗口大小是怎麼樣變化的,我們先需要理解它的含義。最簡單的方式就是認為窗口大小"意味著接收方能接收數據的大小",這也是說接收 端設備再應用程序讀取buffer中數據之前,能從對端連接處理多少數據。比如說server端窗口大小是360,那麼就意味著server端一次只能從 客戶端接收不超過360bytes的數據。當server端收到數據,它會將數據放到buffer裡,然後server端必須對這份數據做兩件事
1. server端必須發送一個 ACK 到client端來確認數據已經收到
2. server端必須處理這份數據,把它交給對應的應用程序
要區分上面兩件事對理解窗口很重要,接收方收到數據後會確認,但是數據並不一定是裡面就是從buffer裡取出的,這是受應用層邏輯控制的。所以很 有可能如果接收數據過快,而取出數據更慢,就會導致buffer滿。一旦這種情況發生,窗口大小就開始調整來防止接收方負載過高。
正是因為窗口大小的調整可以用來調節數據傳輸的速率,所以就可以實現TCP的流控,在傳輸層的流控就是典型的例子,流控對於TCP的通信是很重要的,通過增大或者減小窗口的大小,client和server各自確保彼此設備發數據和收數據平衡。
下面舉一個例子,來看TCP窗口大小變化怎樣實現流控。client端和server端已經三次握手建立TCP連接,總窗口大小是TCP建立連接時 候確定的。黑色框代表client和server總的窗口大小,紅色框代表實際可用的窗口大小。初始化的時候默認client和server總窗口和可用 端口分別都是360。另外,假設Client總共只發送360bytes數據,所以總窗口大小不會往前移動。
窗口就是量化接收端和服務端當前能處理數據的能力。個人理解,如發現接收端的窗口越來越小,或者越來越大,都可能會有問題。
1. 接收端的窗口越來越小,那麼就是接收端處理不過來(1.發的程序太快,太多;2.收的程序太慢,太少;3.發端帶寬比收端帶寬更大),會導致接收端發送給發送端的窗口變小,從而發送端調整發送窗口大小,降低發送速度,網絡流量就會下降。 2. 接收端的窗口越來越大,那麼就是發送端處理不過來(1.收的程序太快,太多;2.發的程序太慢,太少;3.發端帶寬比收端帶寬更小),會導致接收端發送給發送端的窗口變大,從而發送端調整發送窗口大小,增加發送速度,網絡流量就會升高。