1. 程式人生 > >TCP解讀(滑動窗口)

TCP解讀(滑動窗口)

臨時 接口 ip數據報 系統 觀察 因此 http 功能 恢復

基礎知識解讀

TCP是TCP/IP協議族中非常復雜的一個協議。它具有以下特點:

1:面向連接的運輸層協議。在使用TCP協議之前,首先需要建立TCP連接。傳送數據完畢後,必須釋放已經建立的TCP連接。

2:一條TCP連接有兩個端點,連接是點對點的。

3:提供可靠交付的服務。通過TCP連接傳送的數據,不會出現差錯不會丟失並且按序到達。

4:提供全雙工通信。TCP允許通信雙方的應用程序進程在任何時候都能發送數據。TCP連接的兩端都設有緩存,分為發送緩存和接收緩存,用來臨時存放雙向通信的數據。發送時,應用程序把數據傳給TCP的緩存後,就可以做自己的事情了。TCP會在合適的時候把數據發送出去。接收時,TCP把接收到的數據放入緩存,供上層的應用程序讀取。

5:面向字節流。雖然應用程序和TCP的交互是一次一個數據塊,但TCP把應用程序交下來的數據看成一串無結構的字節流。TCP對應用進程一次把多長的報文發送到TCP緩存中是不關心的。TCP根據對方給出的窗口值和當前網絡的擁塞程度決定一個報文段包含多少字節。如果應用程序傳到TCP緩存的數據塊太長,TCP就會把它劃分短些再傳送。如果應用程序發來的數據太少時,TCP將會等待積累足夠多的字節後再構成報文段發送出去。

TCP連接的端點叫做套接字。它是由IP和端口號構成。每一條TCP連接唯一的被通信兩端的兩個端點所確定。同一個IP地址可以有多個不同的TCP連接,而同一個端口號也可以出現在多個不同的TCP連接中。

TCP發送的報文段是交付給IP層傳送的,但IP層只提供盡最大努力的交付。也就是說TCP下面的網絡所提供的是不可靠的服務。可靠傳輸必須依靠TCP來實現。停止等待協議就是一種方式。

停止等待就是每發送完一個分組就停止發送,等待接收方的確認,在收到確認後再傳送下一個分組。如果發送方在一段時間後仍然沒有收到確認,就認為剛才發送的分組丟失了,因而重傳前面發送過的分組,這被稱為超時重傳。要實現超時重傳,就要在每發送完一個分組後設置一個超時計時器。如果在超時計時器到期之前收到了對方的確認,就撤銷已設置的超時計時器。因此發送方在發送完一個分組之後,必須暫時保存已發送的分組的副本。只有在收到響應的確認後才能清除暫時保留的分組的副本。分組和確認分組都必須進行編號,這樣才能知道哪一個發送過的數據已被確認,那些沒有收到確認。超時計時器設置的重傳時間應該比數據在分組傳輸的平均往返時間更長一些。超時重傳時間的設定是非常復雜的,因為已發送的分組到底經過那些網絡,以及這些網絡會產生多大的延遲都是不確定的。

如果發送方發送了數據後,在超時時間內沒有收到接收方的確認,它會重傳數據。如果此時接受方再次接收到了此數據,它會將此數據丟棄,並向發送方發送確認。發送方沒有收到確認,可能是因為接受方的確認出錯或丟失。發送方還可能收到重復的確認,對待重復的確認只需要丟棄即可。上述可靠的傳輸協議被稱為自動重傳請求ARQ(Automatic Repeat Request)。采用停止等待協議可能會導致信道利用率非常低,為了提高傳輸效率,需要使用流水線傳輸。也就是說發送方可以連續發送多個分組,不必沒發完一個分組就停下來等待對方的確認。這樣可以使信道上一直有數據不間斷的在傳送。這被稱為連續ARQ協議或滑動窗口協議。它比較復雜但卻是TCP協議的精髓

滑動窗口

所謂滑動窗口就是說位於此窗口內的分組可以被連續的發送出去,而不需要等待對方的確認。發送方每收到一個確認,就會把發送窗口向前滑動一個分組的位置。假設此時1-5個分組位於發送窗口內,這5個分組就會被連續的發送出去。當發送方收到第一個分組的確認後,就會向後移動一個分組的位置,此時就可以發送第六個分組了。接收方一般都采用累積確認的方式。也就是說,接收方不必對收到的每個分組逐個發送確認,而是可以收到幾個分組後,對按序到達的最後一個分組發送確認。這樣就表示到這個分組為止的所有分組都被正確接收。如果此時發送方發送了前5個分組,而第三個分組丟失了,這是接收方只能對前兩個分組發送確認。發送方不知道後面三個分組的下落。實際上僅僅第三個分組沒有收到,但是發送方仍然會發送後三個分組。

下圖顯示了滑動窗口協議:

技術分享圖片

上面圖中,將字節從1到11進行編號。接收方通告的窗口稱為提供的窗口,它覆蓋了從4到9字節的區域,表明接收方已經確認了3字節在內的數據,且通告窗口大小為6。發送方計算它的可用窗口,該窗口表明多少數據可以立即被發送,這就是常見的win選項

==========================================================================
當接收方確認數據後,這個滑動窗口不時的向右移動。窗口兩個邊沿的相對運動增加或減少了窗口的大小。我們使用三個術語來描述窗口左右邊沿的運動:

技術分享圖片

(1)窗口合攏:窗口左邊沿向右邊沿靠近,這種現象發生在數據被發送和確認時
(2)窗口張開:窗口右邊沿向右移動,運行發送更多的數據,這種現象發生在另一端的接受進程讀取已經確認的數據,並釋放了TCP的接受緩存時
(3)窗口收縮:窗口右邊沿向左移動,這種方式不建議使用。
如果左邊沿到達右邊沿,則稱為一個零窗口,此時發送方不能發送任何數據。
===========================================================================
下圖顯示了最上面例子的滑動窗口協議的動態性:

技術分享圖片

1)發送方不必發送一個全窗口大小的數據;

(2)來自接收方的一個報文段確認數據把窗口向右滑動。這是因為窗口的大小是相對於確認序號的;
(3)報文7和報文8變化,可以看出窗口的大小可以減小,但是窗口的右邊沿卻不能向左移動;
(4)接收方在發送一個ACK前不必等待窗口被填滿。
==================================================================
窗口大小
由接收方提供的窗口大小通常可以由接受進程控制,這將影響TCP的性能。插口API運行進程設置發送和接收緩存的大小。接收緩存的大小是該連接上所能夠告知的最大窗口大小。
*************************************************************************************************
PUSH標誌
發送方使用PUSH通知接收方將所有收到的數據全部提交給接收進程。這裏的數據包括和PUSH一起傳送的數據,以及接收方TCP已經為接收進程收到的其它數據。
在最初的TCP規範中,一般假定編程接口允許發送進程告訴它的TCP何時設置PUSH標誌。
(1)通過允許客戶應用程序通知其TCP設置PUSH標誌,客戶進程通知TCP在向服務器發送一個報文段時不要因等待額外數據而使已提交數據在緩存中滯留;
(2)類似地,當服務器的TCP接收到一個設置了PUSH標誌的報文段時,它需要立即將這些數據遞交給服務器進程,而不能等待判斷是否還會額外的數據到達。
如果待發送的數據將清空發送緩存,則大多數的源於伯克利的實現能夠自動設置PUSH標誌。這意味著我們能夠觀察到每個應用程序寫的數據均被設置了PUSH標誌,因為數據在寫的時候立即被發送。

  TCP首部

TCP是面向字節流的,但是TCP傳送的數據卻是報文段。一個TCP報文段分為首部和數據兩部分。只有真正弄清TCP的首部各字段的作用才能掌握TCP的原理。

TCP的前20個字節是固定的。後面的40字節是根據需要增加的。因此TCP首部的最小長度時20。

1:源端口和目的端口:各占兩個字節。

2:序號:四個字節。共2的32次方個序號。TCP連接中傳送的字節流中的每一個字節都按順序編號。此處的序號字段指的是本報文段所發送的數據第一個字節的序號。

3:確認號:4個字節。表示期望收到對方下一個報文段的第一個數據字節的序號。如確認號是N,則表明序號N-1之前的數據都正確收到。確認號也是4個字節,可以對4GB數據進行編號。

4:數據偏移,4位。它指出TCP報文段的數據起始處距離TCP報文段起始處有多遠。這個字段實際上指出了TCP的首部。由於首部中有長度不確定的選項字段,因此此數據偏移是必要的。數據偏移只有4位,但是它的一個單位代表4字節。因此數據偏移的最大值是60(15*4)。即TCP首部的最大長度。

5:保留 6位。保留為以後使用。都是0.

6:緊急URG 當此處為1時,表明緊急指針字段有效。它告訴系統此報文段有緊急數據,需要盡快傳送。系統會把緊急數據插入TCP緩存的最前面。它和緊急指針字段配合使用。

7:確認ACK:當ACK=1時,確認號字段才有效。當ACK=0時確認號無效。當連接建立前ACK=0,建立之後ACK就一直是1了。

8:推送PSH。當PSH=1時,系統會立即將此報文段發送出去,而不再等待整個緩存都被填滿後才向上交付。

9:復位RST。當其為1,時,表明TCP出現嚴重錯誤,必須釋放連接然後再重新建立連。

10:同步SYN:在連接建立時用來同步序號。當其為1而ACK=0時,表明這是一個(同步)連接請求報文段。當對方同意後,應在響應報文段中使用SYN=1,ACK=1。因此SYN=1,要麽表示連接請求要麽表示連接接受報文。

11:終止FIN:用來釋放連接。當其為1時,表明此報文段的發送方的數據已經發送完畢,要求釋放連接。

12:窗口:2字節。窗口指發送方的接收窗口。它告訴對方:從本報文段首部中的確認號算起,接收方目前允許對方發送的數據量。之所以有此限制是因為接收方的數據緩存空間是有限的。它指出現在允許對方發送數據量。由於接收緩存不斷變化,因此窗口值也不斷變化。

13:檢驗和:2字節。檢驗和檢驗 的是首部和數據這兩部分。在計算時還應加上12字節的偽首部。

14:緊急指針:2字節,此字段只在緊急URG=1時才有意義。它指出本報文段中緊急數據的字節數。由於緊急數據放在了緩沖區最前方,緊急指針指出的是緊急數據的末尾在報文段的位置。當所有的緊急數據都處理完後,TCP 就告訴應用程序恢復正常操作。

15:選項:長度可變,最長可達40字節。當沒有選項時,首部長度時20.

MSS是選項的一種。它被稱為最大報文段長度,是每個TCP報文段中數據字段的最大長度。它加上TCP首部才是整個TCP報文段。再加上20字節的IP首部才能組裝成一個IP數據報。當MSS非常小時,網絡的利用率就低。如果發送只含一個字節的數據時,在IP層傳輸至少需要40字節的開銷(IP頭20字節,TCP頭至少20)。到鏈路層還需要開銷。如果MSS非常大,在IP層傳輸時就可能要分片,到終點後再將各個分片組裝成原來的TCP報文段,這也會使開銷增大。因此,MSS可以盡量大,只要在IP層傳輸時不分片就行了。MSS的默認長度時536。

窗口擴大選項是為了擴大窗口,窗口字段長度是16位,因此最大的窗口大小是64字節。窗口擴大選項占3個字節。每一個字節表示移位值。新的窗口值等於原來的16+窗口擴大選項的值。這相當於把窗口值向左移動移位值位。

時間戳選項占10字節,最主要的兩個地段是:時間戳值和時間戳回送回答字段。

時間戳選項具有以下兩個功能

1:計算往返時間。

2:用於處理TCP序號超過2的32次方的情況。這又被稱為防止序號繞回。在報文段中加入時間戳就可以區分新的報文段和遲到很久的報文段。

socket的兩端分別有兩個窗口,發送窗口和接收窗口。滑動窗口的單位是字節,假設A收到了B的確認報文段,其中窗口時20,而確認號是31,這表明B期望接受的下一個序號是31,到序號30為止的數據已經收到了。根據這兩個數據,A就構造自己的發送窗口。它的起始值為31,而末尾值為50。發送窗口表示在沒有收到B的確認前,A可以連續把窗口內的數據都發送出去。

凡是已經發送過得數據,在未收到確認之前都必須暫時保留,以便在在超時重傳。發送窗口內的序號表示允許發送的序號。

發送窗口與緩存的關系。

發送窗口存儲應用程序將要發送的數據,以及發送但卻為收到確認的數據。 發送窗口只是發送緩存的一部分,已經被確認過的數據應當從發送緩存中刪除。因此發送緩存和發送窗口的後沿是重合的。

接收緩存用來暫時存放按需到達的,但還未被應用程序讀取的數據以及未按序到達的數據。 如果收到的分組有差錯,就要丟棄。如果接收應用程序來不及讀取,接收緩存就會被填滿,就會減少接受窗口,直到減為0。反之就可以增大。

雖然發送方的發送窗口是根據接收方方接收窗口設置但是,但同一時刻,發送窗口並不一定與接收窗口相同。這是因為通過網絡傳送窗口值需要經歷一定的延遲。

TCP要求接收方必須有累計確認的功能,這樣可以減小傳輸開銷。接收方可以在合適的時候發送確認,也可以在自己有數據發送時把確認信息捎上。但應該註意的是接收方不應過分推遲發送確認,否則會導致發送方不必要的重傳,這反而會浪費網絡資源。

TCP利用滑動窗口來實現流量控制。所謂流量控制就是讓發送方的發送速率不要太快,要讓接收方來得及接受。在連接建立時,發送方告訴接收方我的接受窗口是x,接收方收到後會設置自己的發送窗口。發送方的發送窗口不能超過接收方給出的接收窗口的數值。TCP窗口的單位是字節,而不是報文段。在每次發送數據是報文段內會將此時接受窗口告訴發送者。發送者會根據收到的報文段接收窗口的值調整自己的發送窗口。當接收方接收緩存滿時就發送給發送方零窗口,告訴發送方停止發送。假設過一段時間接收方調整接收窗口為100,而此報文段在傳送過程中丟失,這就導致發送方等待接收方的非零窗口通知,而接收方在等待發送方的數據。這樣就導致了死鎖。為了防止這種情況,TCP為每個連接設置一個持續計時器。TCP連接的一方收到零窗口通知後,就啟動計時器,設置的時間到期後它會發送一個探測報文段。如果此時返回的仍然是零窗口,則重新設定計時器。如果窗口不是零,那麽死鎖的僵局就可以被打破了。

TCP解讀(滑動窗口)