3 運輸層(二)

4 可靠數據傳輸原理

可靠數據傳輸的實現問題不僅在運輸層出現,也會在鏈路層以及應用層出現。

可靠數據傳輸的框架:爲上層實體提供的服務抽象是:數據可以通過一條可靠的信道進行傳輸。實現這種服務抽象是可靠數據傳輸協議的責任。

由於可靠數據傳輸協議的下層協議也許是不可靠的,因此這是一項困難的任務。TCP是在不可靠的IP端到端網絡層之上實現的可靠數據傳輸協議。更一般的情況是,兩個可靠通信端點的下層可能是由一條物理鏈路組成或是由一個全球互聯網絡組成。

下面討論基於以下假設:分組將以發送它們的次序進行交付,某些可能丟失。這就是說,底層信道將不會對分組重排序。

4.1 構造可靠數據傳輸協議

4.1.1 經完全可靠信道的可靠數據傳輸:rdt1.0

有限狀態機(Finite-State-Machine,FSM)

該發送方和接收方的FSM每個都只有一個狀態。FSM描述圖中的箭頭指示了協議從一個狀態變遷到另一個狀態(上圖每個FSM都只有一個狀態,因此變遷的必定是從一個狀態返回到自身。)

引起變遷的事件顯示在表示變遷的橫線上方,事件發生時所採取的動作顯示在橫線下方。如果對一個事件沒有動作,或沒有事件就在橫線上方或者下方用^符號表示。

1)在發送端:rdt的發送端只通過rdt_send(data)事件接收來自較高層的數據,產生一個包含該數據的分組(經由make_pkt(data)動作),並將分組發送到信道中。實際上,rdt_send(data)事件是由較高層應用過程調用產生的。

2)在接收端:rdt通過rdt_rcv(packet)事件從底層信道接收一個分組,從分組中取出數據(經由extract(packet,data)動作),並將數據上傳給較高層(通過deliver_data(data)動作)。實際上,rdt_rev(packet)事件是由較底層協議的過程調用產生的。

4.1.2 經具有比特差錯信道的可靠數據傳輸:rdt2.0

底層信道更爲實際的模型是分組中的比特可能受損。在分組的傳輸、傳播或緩存的過程中,這種比特差錯通常會出現在網絡的物理部件中。

利用控制報文使得接收方可以讓發送方知道哪些內容被正確接收,哪些內容接收有誤並因此需要重複。在計算機網絡中,基於這樣重傳機制的可靠數據傳輸協議稱爲自動重傳請求(Automatic Repeat reQuest,ARQ)協議。

ARQ協議還需要另外三種協議來處理存在比特差錯的情況:

1)差錯檢測:這些技術需要有額外的比特(除了待發送的初始數據比特之外的比特)從發送方發送到接收方;這些比特將被彙集在rdt2.0數據分組的分組檢驗和字段中。

2)接收方反饋:rdt2.0協議將從接收方向發送方回送ACK(“肯定確認”)或者NAK(“否定確認”)分組。理論上,這些分組只需要一個比特長;用0表示NAK,用1表示ACK。

3)重傳:接收方收到有差錯的分組時,發送方將重傳該分組文。

rdt2.0的發送端FSM有兩個狀態,接收方FSM有一個狀態。但是注意以下事實:

1)當發送方處於等待ACK或NAK的狀態時,它不能從上層獲得更多的數據。這就是說rdt_send()事件不可能出現,僅當接收到ACK並離開該狀態時才能發生這樣的事件。因此,發送方將不會發送一塊新數據,除非發送方確信接收方已正確接收當前分組。rdt2.0協議被稱爲停等(stop-and-wait)協議。

2)它存在一個致命的缺陷,尤其是沒考慮到ACK或NAK分組受損的可能性。

下面考慮ACK或者NAK時的3種可能:

1)

2)增加足夠的檢驗和比特,使發送方不僅可以檢測錯誤,還可以恢復差錯。(這對於產生差錯但不丟失分組的信道,這就可以直接解決問題。)

3)當發送方收到含糊不清的ACK或NAK分組時,只需重傳當前數組分組即可。然而這種方法在發送方到接收方的信道引入可冗餘分組:冗餘分組的困難在於接收方不知道上次發送的ACK或NAK是否被髮送方正確的收到。(解決辦法是:在數據分組中添加一個新字段,讓發送方對其數據分組編號,即將發送數據分組的序號放在該字段。於是,接收方只需要檢查序號即可確定收到的分組是否一次重傳。)

對於停等協議,1比特就夠了,因爲它可以讓接收方知道發送方是否正在重傳一個發送分組,或是一個新分組。

下面是rdt2.1的FSM描述:

下面是rdt2.2的FSM描述:

4.1.3 經具有比特差錯的丟包信道的可靠數據傳輸:rdt3.0

現在假定除了比特受損外,底層信道還會丟包。協議現在必須處理另外兩個關注的問題:怎樣檢測丟包以及發生丟包後該做些什麼。在rdt2.2中已經研發的技術:使用校驗和、序號、ACK分組和重傳等。使得可以解決第二個問題,對於第一個問題,還需要增加一種新的協議機制:

對於第一個問題:解決丟包問題,可以讓發送方負責檢測和恢復丟包工作。假定發送方傳輸一個數據分組,該分組或者接受方對該分組的ACK發生了丟失。這兩種情況發送方都收不到應當到來的接收方的響應。如果發送方願意等待足夠長的時間以便確定分組已丟失,則它只需重傳該數據分組即可。

對於第二個問題:發送方需要等待的時間:發送方與接收方之間的一個往返時延加上接收方處理一個分組的時間(有時該時延很長)。因此,實踐中的做法是發送方選擇一個時間值,以判定可能發生了丟包。如果在這個時間內沒有收到ACK,則重傳分組。這就在發送方到接收方的信道中引入了冗餘數據分組。這個問題在rdt2.2中已經解決。

從發送方來看,重傳是一種很好的方式。爲了實現基於時間的重傳機制,需要一個倒數定時器,在一個給定的時間量過期後,可中斷髮送方。因此發送方需要做到:

1)每次發送一個分組(包括第一次分組和重傳分組)時,便啓動一個定時器。

2)響應定時器中斷。

3)終止定時器。

rdt3.0有時被稱爲比特交替協議(alternating-bit protocol)

數據傳輸協議的要點:在檢驗和、序號、定時器、肯定和否定確認分組這些技術中,每種機制都在協議的運行中起到了必不可少的作用。

4.2 流水線可靠數據傳輸協議

rdt3.0 性能問題的核心在於它是一個停等協議。

停等協議的缺點在於其利用率(發送方實際忙於將發送比特送進信道的那部分時間與發送時間之比)。

解決這種特殊的性能問題的一個簡單方法是:不使用停等方式運行,允許發送方發送多個分組而無需等待確認。這種技術爲流水線:因爲許多從發送方向接收方輸送的分組可以被看成是填充到一條流水線中。

流水線技術對可靠數據傳輸協議帶來如下影響:

1)必須增加序號範圍:因爲每個輸送中的分組必須有一個唯一的序號,而且也許有多個在輸送中未確認的報文。

2)協議的發送方和接收方兩端也許必須緩存多個分組。

3)所需序號範圍和對緩衝的要求取決於數據傳輸協議如何處理丟失、損壞及延時過大的分組。

解決流水線的差錯恢復有兩種基本的方法:回退N步(G0-Back-N,GBN),和選擇重傳(Selective Repeat,SR)。

4.3 回退N步

這裏暫時不太清楚,後續加上。

4.4 選擇重傳

這裏暫時不太清楚,後續加上。

5 面向連接的運輸TCP

TCP是因特網運輸層的面向連接的可靠運輸協議。TCP依賴很多原理:其中包括差錯檢測、重傳、累積確認、定時器以及用於序號和確認號的首部字段。TCP定義在RFC793、RFC1122、RFC1323、RFC2018、以及RFC2581中。

5.1 TCP連接

TCP被稱爲是面向連接的(connection-oriented),這是因爲在一個應用進程可以開始向另一個應用進程發送數據之前,這兩個進程必須先互相“握手”(即它們必須相互發送某些預備報文段,以建立確保數據傳輸的參數)。作爲TCP連接建立的一部分,連接雙方都將初始化與TCP連接相關的許多TCP狀態。

傳輸控制協議/網際協議(Transmission Control Protocal/Internet Protocal,TCP/IP)

1)由於TCP協議只在端系統中運行,而不在中間的網絡元素(路由器和鏈路層交換機)中運行,所以中間的網絡元素不會維持TCP連接狀態。

2)TCP連接提供的是全雙工服務(full-duplex service):如果一臺主機的進程A與另一臺主機上的進程B存在一條TCP連接,則應用層數據就可在進程B流向進程A的同時,也從進程A流向進程B。

3)TCP連接總是點對點(point-to-point)的,即在單個發送方與單個連接方之間連接。

4)假設運行在某臺主機上的一個進程想與另一臺主機上的一個進程建立一條連接,該客戶應用進程首先通知客戶運輸層,它想與服務器上的一個進程建立一條連接。一個客戶程序通過發出下面的命令來實現
clientSocket.connect((serverName,serverPort))

5)三次握手:客戶首先發送一個特殊的TCP報文段,服務器用另一個特殊的TCP報文段來相應,最後,客戶再用第三個特殊報文段作爲響應。前兩個報文段不承載“有效載荷”,也就是不包含應用層數據;而第三個報文段可以承載有效載荷。
由於在這兩臺主機之間發送了3個報文段,所以這種連接建立過程常被稱爲三次握手(three-way handshake)

6)一旦建立一條TCP連接,兩個應用進程之間就可以相互發送數據了。客戶進程通過套接字(該進程之門)傳遞數據流。數據一旦通過該門,它就有客戶中運行的TCP控制了。如下圖所示,TCP將這些數據引導到該連接的發送緩存(send buffer)裏,發送緩存是在三次握手初期設置的緩存之一。

7)首先介紹幾個名詞:

最大報文長度(Maximum Segment Size,MSS):指報文段裏應用層數據的最大長度,而不是指包括TCP首部的TCP報文段的最大長度。個人理解如下圖所示:

最大傳輸單元(Maximum Transmission Unit,MTU):本地發送主機發送的最大鏈路層幀長度。

TCP可以從緩存中取出並放入報文段中的數據數量受限於MSS,MSS通常由MTU來設置,該MSS要保證一個TCP報文段(當封裝在一個IP數據報中)加上TCP/IP首部長度(通常是40字節)將適合單個鏈路層幀。以太網和PPP鏈路層協議都具有1500字節的MTU,因此,MSS的典型值爲1460字節。

8)TCP連接的組成包括:一臺主機上的緩存、變量和與進程連接的套接字,以及另一臺主機的另一組緩存、變量和與進程連接的套接字。

5.2 TCP報文段結構

TCP報文段由首部字段和一個數據字段(包含一塊應用數據)組成。

1)當TCP發送一個大文件時,TCP通常將該文件劃分爲長度爲MSS的若干塊(最後一塊除外,它通常小於MSS)。

2)然而,交互式應用通常傳送長度小於MSS的數據塊。例如,對於像Telnet這樣的遠程登錄應用,其TCP報文段的數據字段經常只有一個字節。由於TCP的首部一般是20字節(比UDP首部多12字節),所以Telnet發送的報文段也許只有21字節長。

3)TCP報文段結構如上圖,其中首部包括:

①源端口號和目的端口號:被用於多路複用/分解來自或送到上層應用的數據。

②檢驗和字段(checksum field)

③32bits的序號字段(sequence number field)和32bits的確認號字段(acknowledgement number field):這些字段被TCP發送方和接收方用來實現可靠數據傳輸服務。

④16bits的接收窗口字段(receive window field):該字段用於流量控制(該字段用於指示接收方願意接受的字節數量)。

⑤4bits的首部長度字段(header length field):字段指示了以32bits的字爲單位的TCP首部的長度。由於TCP選項字段的原因,TCP首部的長度是可變的(通常,選項字段爲空,所以TCP首部的典型長度就是20字節。)

⑥可選與變長的選項字段(options field):該字段用於發送方與接收方協商最大報文段長度(MSS)時,或在高速網絡環境下用作窗口調節因子時使用。

⑦6bits的標誌字段(flag field):

ACK比特:用於指示確認字段中的值是有效的,即該報文段包含一個對已被成功接收報文段的確認。
RST、SYN和FIN比特:用於連接建立和拆除。
PSH比特:該比特被設置時,就指接收方應立即將數據交給上層。
URG比特:用於指示報文段裏存在着被髮送端的上層實體置爲“緊急”的數據。

⑧緊急數據指針字段(urgent data pointer):緊急數據的最後一個字節由16比特的緊急數據指針字段指出。當緊急數據存在並給出指向緊急數據尾的指針的時候,TCP必須通知接收端的上層實體。(在實踐中,PSH、URG和緊急數據指針並沒有使用。爲了完整性,才提到這些字段。

序號和確認號

序號和確認號是TCP報文段首部中兩個最重要的字段。這兩個字段是TCP可靠傳輸服務的關鍵部分。

序號:

TCP把數據看成一個無結構、有序的字節流。因爲序號是建立在傳送的字節流之上,而不是建立在傳送的報文段的序列之上。則一個報文段的序號(sequence number for a segment)是該報文段首字節的字節流編號。

假設主機A上的一個進程想通過一條TCP連接向主機B上的一個進程發送一個數據流。主機A中的TCP將隱式地對數據流中的每一個字節編號。假設數據流由一個500 000字節的文件組成,其MSS爲1000字節,數據流的首字節編號爲0。則TCP將爲該數據流構建500個報文段,給第一個報文段分配序號爲0,第二個報文段分配序號1000,第三個報文段分配序號2000,以此類推。每一個序號被填入到相應TCP報文段首部的序號字段中。

如果序號超過4 294 967 295怎麼辦?即超過5GB的數據如何分配序號?超過32位的存儲了。

確認號:

TCP是全雙工的,因此主機A向主機B發送數據的同時,也許也接收者來自主機B的數據(都是同一條TCP連接的一部分)。從主機B到達的每個報文段中都有一個序號用於從B流向A的數據,主機A填充進報文段的確認號是主機A期望從主機B收到的下一字節的序號。

舉例,主機A已收到來自主機B的包含字節0~535的報文段,以及另一個包含字節900~1000的報文段,由於某種原因,主機A還沒收到字節536~899的報文段。在這個例子中,主機A爲了重新構建主機B的數據流,仍在等待字節536(和其後的字節)。因此,A到B的下一個報文段將在確認號字段中包含536.因爲TCP只確認該流中至第一個丟字節爲止的字節,所以TCP被稱爲提供累積確認(cumulative acknowledgment)。

當主機在一條TCP連接中收到失序報文段時該怎麼辦?TCP RFC並沒有爲此明確規定,而是由TCP的編程人員實現。他有兩個基本的選擇:①接收方立即丟棄失序報文段;②接收方保留失序的字節,並等待缺少的字節以填補該間隔(後一種選擇對網絡帶寬而言更爲有效,是實踐中採用的方法)。

值得注意的是,對客戶到服務器的數據的確認被裝載在一個承載服務器到客戶的數據的報文段中;這種確認被稱爲是被捎帶(piggybacked)在服務器到客戶的數據報文段中的。

5.3 往返時間的估計與超時

TCP如同rdt協議一樣,它採用超時/重傳機制來處理報文段的丟失問題。

1)超時間隔長度的設置?顯然,超時時間間隔必須大於該連接的往返時間(RTT),即從一個報文段發出到它被確認的時間。

2)如何估計往返時間?

3)是否應該爲所有未確認的報文段各設一個定時器?

估計往返時間

報文段的樣本RTT(表示爲SampleRTT)就是從某報文段被髮出(即交給IP)到對該報文段的確認被收到之間的時間量。大多數TCP的實現僅在某個時刻做一次SampleRTT測量,而不是爲每個發送的報文段測量一個SampleRTT.

//指數加權移動平均(Exponential Weighted Moving Average,EWMA)。
//推薦的a=0.25
EstimatedRTT = (1 – a) • EstimatedRTT + a • SampleRTT
//推薦的b=0.25
//DevRTT:RTT偏差,測量RTT的變化。
DevRTT = (1 – b) • DevRTT + b•| SampleRTT – EstimatedRTT |

設置和管理重傳超時間隔

超時間隔應該大於等於EstimatedRTT,否則將造成不必要的重傳。但超時時間間隔也不能比EstimatedRTT大太多,否則當報文段丟失時,TCP不能很快地重傳該報文段,導致數據傳輸時延大。

//推薦TimeoutInterval值爲1秒。超時後,TimeoutInterval值將加倍。
//一旦報文段收到並更新EstimatedRTT後,TimeoutInterval就使用下式
TimeoutInterval = EstimatedRTT + 4 • DevRTT

1)TCP通過使用肯定確認與定時器來提供可靠數據傳輸。TCP確認正確接收到的數據,而當認爲報文段或其確認報文丟失或受損後,TCP會重傳這些報文段。

2)TCP使用流水線,使得發送方在任意時刻都可以有多個已發出但還未確認的報文段存在。一個發送方具有的未被確認報文段的確切個數是由TCP的流量控制和擁塞控制機制決定的。

3.5.4 可靠數據傳輸

對於IP服務,數據報能夠溢出路由器緩存而永遠不能到達目的地,數據報也可能亂序到達,而且數據報中的比特可能損壞。TCP在IP不可靠的盡力而爲服務之上創建一種可靠數據傳輸服務。TCP的可靠數據傳輸服務確保了一個進程從其接收緩存中讀取數據流是無損壞、無間隔、非冗餘和按序的數據流。

接下來討論:

1)簡化版本:發送方只用超時技術來恢復報文段丟失。

2)全面版本:除了使用超時機制外,還使用冗餘確認技術。

簡化版本描述:TCP發送方有3個與發送和重傳有關的主要事件(①從上層應用程序接收數據;②定時器超時;③收到ACK;)

/* Assume sender is not constrained by TCP flow or congestion control, that data from above is less than MSS in size, and that data transfer is in one direction only. */
NextSeqNum=InitialSeqNumber
SendBase=InitialSeqNumber

loop (forever) {
    switch(event)

        event: data received from application above
            create TCP segment with sequence number NextSeqNum
            if (timer currently not running)
                start timer
            pass segment to IP
            NextSeqNum=NextSeqNum+length(data)
            break;

        event: timer timeout
            retransmit not-yet-acknowledged segment with
                smallest sequence number
            start timer
            break;

        event: ACK received, with ACK field value of y
            if (y > SendBase) {
                SendBase=y
                if (there are currently any not-yet-acknowledged segments)
                    start timer
            }
        break;
} /* end of loop forever */

1)TCP從應用程序接收數據,將數據封裝在一個報文段中,並把該報文段交給IP。(①注意到每一個報文段都包含一個序號,這個序號就是該報文段第一個數據字節的字節流編號。②如果定時器還沒有爲某些其他報文段而運行,則當報文段被傳給IP時,TCP就啓動該定時器。)

2)超時:TCP通過重傳引起超時的報文段來響應超時事件。

3)來自接收方的確認報文段(ACK)的到達:TCP將ACK的值y與它的變量SendBase(是最早未被確認的字節序號)進行比較。TCP採用累積確認,所以y確認了字節編號在y之前的所有字節都已經收到。如果y > SenfBase,則該ACK是在確認一個或多個先前未被確認的報文段。因此,發送方更新它的SendBase變量。

一些情況

情況一:

情況二:

情況三:

超時間隔加倍

大多數TCP實現中所做的一些修改:TCP重傳具有最小序號的還未被確認的報文段。只是每次TCP重傳時都會將下一次的超時間隔設爲先前值的兩倍,而不是從EstimatedRTT和DevRTT推算出的值。然而,每當定時器在另兩個事件(即收到上層應用數據或收到ACK)中的任意一個啓動,TimeoutInterval由最近的EstimatedRTT和DevRTT推算得到。

優點:這種修改提供了一個形式受限的擁塞控制。定時器過期很有可能是由網絡擁塞引起的,即太多的分組到達源與目的地之間路徑上一臺(或多臺)路由器的隊列中,造成分組丟失或長時間的排隊時延。在擁塞的時候,如果源持續重傳分組,會使擁塞更加嚴重。因此,TCP使用更好的方法,每個發送方的重傳都是經過越來越長的時間間隔後進行的。

快速重傳

問題:超時觸發重傳存在的問題是超時週期可能相對較長,當一個報文段丟失時,這種長超時週期迫使發送方延遲重傳丟失的分組,因而增加了端到端時延。

解決辦法:冗餘ACK(duplicate ACK):就是再次確認某個報文段的ACK,而發送方先前已經收到對該報文段的確認。(通過下面理解:發送方通常在超時事件發生之前通過注意所謂冗餘ACK來較好地檢測到丟包情況。)

TCP接收方的ACK生成策略:

因爲發送方經常一個接一個地發送大量的報文段,如果一個報文段丟失,就很可能引起許多一個接一個的冗餘ACK。如果TCP發送方接收到對相同數據的3個冗餘ACK,它把這當做一種暗示,說明跟在這個已被確認3次的報文段之後的報文段已經丟失(爲何是3個冗餘ACK?)。一旦受到3個冗餘ACK,TCP就執行快速重傳(fast retransmit),即在該報文段的定時器過期之前重傳丟失的報文段。

快速重傳的TCP,其ACK收到事件:

event: ACK received, with ACK field value of y
    if (y > SendBase) {
        SendBase=y
        if (there are currently any not yet acknowledged segments)
            start timer
        }
    else { /* a duplicate ACK for already ACKed segment */
        increment number of duplicate ACKs received for y
        if (number of duplicate ACKS received for y==3)
            /* TCP fast retransmit */
            resend segment with sequence number y
        }
    break;

是回退N步還是選擇重傳

TCP是一個GBN協議還是一個SR協議?

1)TCP確認是累積式地、正確地接收,但是失序的報文段是不會被接收方逐個確認的。TCP發送方僅需維持已發送過但未被確認的字節的最小序號(SendBase)和下一個要發送的字節的序號(NextSeqNum)。這個意義下,TCP看起來更像一個GBN風格的協議。

2)但是TCP和GBN協議之間有着一些顯著的區別,許多TCP實現會將正確接收但失序的報文段緩存起來。考慮一下當發送方發送一組報文段1、2、…N的序列時,所有的報文段都是在接收方按序無差錯的情況下到達的。進一步假設,對包n小於N的確認報文丟失了,但是其餘的N-1確認報文在它們各自的超時之前到達了發送端。在這個例子中,GBN不僅會重新傳輸數據包n,還會傳送所有的後續分組,n+1 n+2,…N。另一方面,TCP將重傳至多一個報文段,即報文段n。此外,如果報文段n+1的確認報文在報文段n超時之前到達。TCP甚至不會重新傳輸段n。

3)TCP提出的一種修改意見是所謂的選擇確認(selective acknowledgment)[RFC2018],它允許TCP接收方有選擇地確認失序報文段,而不是累積地確認最後一個正確接收的有序報文段。當該機制與選擇重傳機制結合起來使用時(即跳過重傳那些已被接收方選擇性地確認過的報文段),TCP看起來像SR協議。因此,TCP的差錯恢復機制最後被分類爲GBN協議與SR協議的混合體。

5.5 流量控制

一條TCP連接的每一側主機都爲該連接設置了接收緩存。當該TCP連接收到正確、按序的字節後,他就將數據放入到接收緩存。(注意:相關聯的進程會從該緩存中讀取數據,但不是數據剛一到就立即讀取。)

TCP爲應用程序提供了流量控制服務(flow-control-service)以消除發送方使接收方緩存溢出的可能性。

流量控制服務(flow-control-service):是一個速度匹配服務,即發送方的發送速率與接收方應用程序的讀取速率相匹配。

擁塞控制(congestion control):TCP發送方可能因爲IP網絡的擁塞而被抑制。

注意:本節假設TCP接收方丟棄失序的報文段。

接收窗口(receive window):用於給發送方一個指示:該接收方還有多少可用的緩存空間。TCP通過讓發送方維護一個稱爲接收窗口的變量來控制流量的控制。

因爲TCP是全雙工通信,在連接兩端的發送方都各自維護一個接收窗口。

假設主機A通過一條TCP連接向主機B發送一個大文件。主機B爲連接分配了一個接收緩存RecvBuffer表示其大小。

//定義以下變量
• LastByteRead: the number of the last byte in the data stream read from the buffer by the application process in B
• LastByteRcvd: the number of the last byte in the data stream that has arrived from the network and has been placed in the receive buffer at B
//由於TCP不允許已分配緩存溢出,下式必須成立:
LastByteRcvd – LastByteRead ≤ RcvBuffer
//接收窗口用rwnd表示,根據緩存可用空間數量來設置:
rwnd = RcvBuffer – [LastByteRcvd – LastByteRead]

由於該空間是隨着時間變化的,所以rwnd是動態的,rwnd也稱爲滑動窗口。

1)連接是如何使用變量rwnd提供流量控制服務?主機B通過把當前的rwnd值放入它發送給主機A的報文段接收窗口字段中,通知主機A它在該連接的緩存中還有多少可用空間。

開始時,主機B設定rwnd = RecvBuffer。主機A輪流跟蹤兩個變量LastByteSent和LastByteAcked。(LastByteSent-LastByteAcked:表示主機A發送到連接中但未被確認的數據量)。通過將未確認的數據量控制在rwnd以內,就可以保證主機A不會使主機B的接收緩存溢出。

因此,主機A在整個生命週期需保證:LastByteSent – LastByteAcked ≤ rwnd

2)這個方案有一個小技術問題。 假設主機B的接收緩衝區已滿,使得rwnd = 0。在將rwnd = 0通知給主機A,也假設B沒有什麼可以發送到A。現在考慮發生什麼情況,當B中的應用進程清空緩衝區時,TCP不會向主機A發送新的帶有rwnd新值的新報文段; 實際上,TCP只有它有數據或者有確認要發送時纔會發送保文段向主機A。因此,主機A不知道Host B的接收緩衝區已有新的空間了。即主機A被阻塞,並且不能傳輸更多的數據! 爲了解決這個問題,TCP規範要求:當B的接收窗口爲零時,主機A繼續發送一個只有1個字節數據的報文段。 這些報文段將會被接收器確認。最終緩衝區將開始清空,並且確認報文裏將包含一個非0的rwnd值。

5.6 TCP連接管理

本節關注建立和拆除一條TCP連接。即三次握手,四次揮手。

建立連接

TCP連接的建立會顯著地增加人們感受到的時延。客戶中的TCP會用以下方式與服務器中的TCP建立一條

TCP連接:

TCP SYN報文段

1)第一步:客戶端TCP首先向服務器端的TCP發送一個特殊的TCP報文段(TCP SYN報文段:該報文段不包含應用層數據,但在報文段的首部中的一個標誌位SYN被置爲1.)。另外,客戶會隨機選擇一個初始序號(client_isn),並將次編號放置與該起始的TCP SYN報文段的序號字段中。該報文段會被封裝在一個IP數據報中,併發送給服務器。

SYNACK報文段

2)第二步:一旦包含TCP SYN報文段的IP數據報到達服務器主機(假定它的確達到了),服務器會從該數據報中提取出TCP SYN報文段,爲TCP連接分配TCP緩存和變量,並向該客戶TCP發送允許連接的報文段(分配的這些緩存和變量,使得TCP易於受到SYN洪泛的拒絕服務攻擊),這個允許連接的報文段(SYNACK報文段:該首部有3個重要信息①SYN置爲1;②確認號字段被置爲client_isn+1;③服務器選擇自己的初始序號server_isn,並將其放在TCP報文段首部的序號字段中。)不包含應用層數據。

3)在收到SYNACK報文段後,客戶也要給該連接分配緩存和變量。客戶主機則向服務器發送另外一個報文段;這最後一個報文段對服務器的允許連接的報文段進行了確認(首部中:①確認字段爲server_isn+1;②序號字段爲client_isn+1;③SYN比特置爲0)。該三次握手的第三個階段可以在報文段負載中攜帶客戶到服務器的數據。

在以後的每一個報文段中,SYN比特都被置爲0;這種連接創建過程被稱爲3次握手(three-way handshake)。

TCP拆除:

參與一條TCP連接的兩個進程中的任意一個都能終止該連接。當連接結束後,主機中的“資源(緩存和變量)”將被釋放。

假設某客戶打算關閉連接:

1)客戶應用進程發送一個關閉連接命令:客戶TCP向服務器進程發送一個特許TCP報文段(首部的標誌位FIN置爲1)

2)當服務器接收到該報文段後,就向發送方發送一個確認報文段。

3)服務器發送它自己的終止報文段,其FIN比特置爲1.

4)客戶對這個服務器的終止報文段進行確認。(此時,兩個主機用於連接的所有資源都被釋放了。)

客戶TCP狀態圖

1)客戶TCP開始處於CLOSED狀態。

客戶應用程序發起一個新的連接,則客戶TCP向服務器中的TCP發送一個SYN報文段

2)發送過SYN報文段後,客戶TCP進入了SYN_SENT狀態。

接着,等待來自服務器TCP的對客戶所發報文段進行確認且SYN比特被置爲1的一個報文段(SYNACK報文段)

3)收到SYNACK報文段之後,客戶TCP進入ESTABLISHED(已建立)狀態。

當處在ESTABLISHED狀態時,TCP客戶就能發送和接收包含有效載荷數據(即應用層產生的數據)的TCP報文段了。

4)假設客戶要決定關閉該連接,這引起客戶TCP發送一個帶有FIN比特被置爲1的TCP報文段,進入FIN_WAIT_1狀態。

客戶等待來自服務器的帶有確認的TCP報文段。

5)收到上述報文段後,客戶TCP進入FIN_WAIT_2狀態。

客戶等待來自服務器的FIN比特置爲1的另一個報文段。

6)收到上述報文段後,客戶TCP對服務器發送確認報文段進行確認,並進入TIME_WAIT狀態。

假設ACK丟失,TIME_WAIT狀態使TCP客戶重傳最後的確認報文。在TIME_WAIT狀態中所消耗的時間是與具體實現有關的,而典型值是30s,1min,或2min。經過等待後,連接就正式關閉,客戶端所有資源(包括端口號)將被釋放。

服務器TCP狀態圖

下面考慮一臺主機接收到一個TCP報文段,其端口號或源IP地址與該主機上進行中的套接字都不匹配。則該主機將向源發送一個特殊重置報文:該報文段將RST標誌位置爲1.當一臺主機接收一個UDP分組,它的目的端口與進行中的UDP套接字不匹配,該主機發送一個特殊的ICMP數據報。

nmap是一個功能強大的工具,該工具不僅能“偵查”打開的TCP端口,也能“偵查”UDP端口,還能偵查防火牆及其配置,甚至能偵查應用程序的版本和操作系統,大多數都能通過操作TCP連接管理報文段完成。可以從http://www.nmap.org中下載nmap。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章