1. 程式人生 > 其它 >(二十五)運輸層--TCP的流量控制

(二十五)運輸層--TCP的流量控制

TCP的流量控制

滑動視窗

一般來說,我們總是希望資料傳輸得更快一些。但如果傳送方把資料傳送得過快,接收方就可能來不及接收,這就會造成資料的丟失。所謂流量控制(flow control)就是讓傳送方的傳送速率不要太快,要讓接收方來得及接收。利用滑動視窗機制可以很方便的在TCP連線上實現對傳送方的流量控制。看下面這個例子:

假設A向B傳送資料。在連線建立時,B告訴了A:我的接收視窗是400。因此,傳送方的傳送視窗不能超過接收方給出的接收視窗的數值。請注意,TCP的視窗單位是位元組,不是報文段。再假設每一個報文段為100位元組長,而資料報文段序號的初始值設為1。從上圖可發現,接收方的主機B進行了三次流量控制。第一次把視窗減小到300,第二次減小到100,最後減到0,即不允許傳送方再發送資料了。這種使傳送方暫停傳送的狀態將持續到主機B重新發出一個新的視窗值為止。B向A傳送的三個報文段都設定了ACK = 1,只有在ACK = 1 時,確認號欄位才有意義。

現在我們考慮一種情況。B向A傳送了零視窗的報文段後不久,B的接收快取又有了一些儲存空間。於是B向A傳送了rwnd = 400的報文段。然而這個報文段在傳送過程中丟失了。A一直等待收到B傳送的非零視窗的通知,而B也一直等待A傳送的資料。如果沒有其它措施,這種互相等待的死鎖局面將一直延續下去。為了解決這個問題。TCP為每一個連線設有一個持續計時器。只要TCP連線的一方收到對方的零視窗通知,就啟動持續計時器。若持續計時器設定的時間到期,就傳送一個零視窗探測報文段(僅攜帶1位元組的資料),而對方就在確認這個探測報文段時給出了現在的視窗值。如果視窗仍然是零,那麼收到這個報文段的一方就重新設定持續計時器。如果視窗不是零,那麼死鎖的僵局就可以打破了。TCP規定,即使設定為零視窗,也必須接收以下幾種報文段:零視窗探測報文段、確認報文段、攜帶緊急資料的報文段。

傳輸效率

應用程序把資料傳送到TCP的傳送快取後,剩下的傳送任務就由TCP來控制了。可以用不同的機制來控制TCP報文段的傳送時機。第一種機制是TCP維持一個變數,它等於最大報文段長度MSS。只要快取中存放的資料達到MSS位元組時,就組裝成一個TCP報文段傳送出去。第二種機制是由傳送方的應用程序指明要求傳送報文段,即TCP支援的推送操作。第三種機制是傳送方的一個計時器期限到了,這時就把當前已有的快取資料裝入報文段傳送出去,但長度不能超過MSS。

但是,如何控制TCP傳送報文段的時機仍然是一個較為複雜的問題。

例如,一個互動式使用者使用一條TELNET連線。假設使用者只發一個字元,加上20位元組的首部後,得到21位元組長的TCP報文段,再加上20位元組長的IP首部,形成41位元組長的IP資料報。在接收方TCP立即發出確認,構成的資料報是40位元組長。若使用者要求遠地主機回送這一字元,則又要發回41位元組長的IP資料報和40位元組長的確認IP資料報。這樣,使用者僅發1個字元時,線路上就需傳送總長度為162位元組,共4個報文段。當線路頻寬並不富裕時,這種傳送方法的效率的確不高。因此應適當推遲發回確認報文,並儘量使用捎帶確認的方法。

在TCP的實現中廣泛使用Nagle演算法。演算法如下:若傳送應用程序把要傳送的資料逐個位元組的送到TCP的傳送快取,則傳送方就把第一個資料位元組先發送出去,把後面到達的資料位元組都快取起來。當傳送方收到對第一個資料字元的確認後,再把傳送快取中的所有資料組裝成一個報文段傳送出去,同時繼續對隨後到達的資料進行快取。只有在收到對前一個報文段的確認後才繼續傳送下一個報文段。當資料到達較快而網路速率較慢時,用這樣的方法可明顯減少所用的網路頻寬。Nagle演算法還規定,當到達的資料已達到傳送視窗大小的一半或已達到報文段的最大長度時,就立即傳送一個報文段。這樣做,就可以有效的提高網路的吞吐量。

另一個問題叫做糊塗視窗綜合徵,有時也會使TCP的效能變壞。設想一種情況:TCP接收方的快取已滿,而互動式的應用程序一次只從接收快取中讀取一個位元組,然後向傳送方確認,並把視窗設定為1個位元組(但傳送的資料報是40位元組)。接著,傳送方又發來一個位元組的資料。接收方發回確認,仍然將視窗設定為1個位元組。這樣進行下去,使網路的效率很低。要解決這個問題,可以讓接收方等待一段時間,使得或者接收快取已有足夠空間容納一個最長的報文段,或者等到接收快取已有一半空閒的空間。只要出現這兩種情況之一,接收方就發出確認報文,並向傳送方通知當前的視窗大小。此外,傳送方也不要傳送太小的報文段,而是把資料積累成足夠大的報文段,或達到接收方快取的空間的一半大小。

上面兩種方法可配合使用。使得在傳送方不傳送很小的報文段的同時,接收方也不要在快取剛剛有了一點小的空間就急忙把這個很小的視窗大小資訊通知給傳送方。