TCP滑動窗口詳解
http://lyjdamzwf.blog.163.com/blog/static/75206837201193373226/
TCP滑動窗口(Sliding Window)
滑動窗口協議可以用圖四來形象表示。

圖中我們已經將字節進行了1到11的編號。由接收者通告的窗口稱為提議窗口(offered window),它覆蓋了第4到第9個字節,意味着接收方已經確認了第3字節之前(包括第3字節)的數據,並且通告窗口的大小是6。窗口大小與確認的順序號(acknowledged sequence number)有關。發送者計算它的可用窗口(usable window),用以度量它可以立即發送多少數據。
隨着接收者對收到數據的確認,滑動窗口隨時向右移動。窗口兩端的相關運動增加或減少着窗口大小。我們使用3個術語來描述窗口邊緣(edge)的左右運動。
1. 當窗口左邊緣靠近右邊緣時稱窗口閉合(window closes)。窗口閉合發生在數據已經發送並被確認的情況下。
2. 當窗口右邊緣向右移動時稱窗口打開(window opens)。窗口打開發生在另一端的接收進程讀取已確認數據的時候,它釋放了TCP接收緩沖區的空間。
3. 當窗口右邊緣向左移動時稱窗口收縮(window shrinks)。Host Requirement RFC強烈不鼓勵這種做法,但TCP必須能夠在一端發生這種情況時進行處理。
圖五表示了這三個術語。由於窗口的左邊緣是受從連接另一端收到的確認號來控制的,因此它不會向左移動。如果收到一個ACK要求將左邊緣向左移動,那么它是一個重復的(duplicate)的確認,並被丟棄。

如果窗口左邊緣重合了右邊緣,就稱它為零窗口(zero window)。它將停止發送者傳輸任何數據。
示例
圖六顯示了圖一數據傳輸中TCP滑動窗口的動態變化
以此圖為例,我們可以總結幾個要點:
1. 發送者不必傳送滿窗口大小的數據。
2. 收到接收者對數據的確認后,窗口向右滑動。這是由於窗口大小與確認順序號相關。
3. 從段7到段8的變化,可以看出窗口可以減小,但窗口右邊緣不能向左移動。
4. 接收者不必等待窗口被填滿才發送確認。在許多實現中,接收者每收到兩個段發送一個確認。
TCP滑動窗口和socket緩沖區之間的關系
一、TCP的滑動窗口大小實際上就是socket的接收緩沖區大小的字節數
二、對於server端的socket一定要在listen之前設置緩沖區大小,因為,accept時新產生的socket會繼承監聽socket的緩沖區大小。對於client端的socket一定要在connet之前設置緩沖區大小,因為connet時需要進行三次握手過程,會通知對方自己的窗口大小。在connet之后再設置緩沖區,已經沒有什么意義。
三、由於緩沖區大小在TCP頭部只有16位來表示,所以它的最大值是65536,但是對於一些情況來說需要使用更大的滑動窗口,這時候就要使用擴展的滑動窗口,如光纖高速通信網絡,或者是衛星長連接網絡,需要窗口盡可能的大。這時會使用擴展的32位的滑動窗口大小。
四、滑動窗口移動規則:
1、窗口合攏:在收到對端數據后,自己確認了數據的正確性,這些數據會被存儲到緩沖區,等待應用程序獲取。但這時候因為已經確認了數據的正確性,需要向對方發送確認響應ACK,又因為這些數據還沒有被應用進程取走,這時候便需要進行窗口合攏,緩沖區的窗口左邊緣向右滑動。注意響應的ACK序號是對方發送數據包的序號,一個對方發送的序號,可能因為窗口張開會被響應(ACK)多次。
2、窗口張開:窗口收縮后,應用進程一旦從緩沖區中取出數據,TCP的滑動窗口需要進行擴張,這時候窗口的右邊緣向右擴張,實際上窗口這是一個環形緩沖區,窗口的右邊緣擴張會使用原來被應用進程取走內容的緩沖區。在窗口進行擴張后,需要使用ACK通知對端,這時候ACK的序號依然是上次確認收到包的序號。
3、窗口收縮,窗口的右邊緣向左滑動,稱為窗口收縮,Host Requirement RFC強烈建議不要這樣做,但TCP必須能夠在某一端產生這種情況時進行處理。