1. 程式人生 > >我是如何講清楚TCP協議是如何保證可靠傳輸的

我是如何講清楚TCP協議是如何保證可靠傳輸的

1、UDP:
(1)UDP,user datagram protocol,使用者資料報協議,不提供複雜的控制機制,利用IP提供面向無連線的通訊服務,並且它是將應用程式傳送過來的資料包在收到的那一刻,立即按照原樣傳送到上的一種機制。

(2)即使在網路擁堵的情況下,UDP也無法進行流量控制等避免網路擁塞的行為。此外,在傳輸過程中如果出現丟包,UDP也不負責重發,甚至當資料包的到達順序亂掉之後也沒有糾正順序的功能。因此,如果需要這些細節控制的話,就需要在採用UDP協議的應用層去作出處理。

(3)由於UDP面向無連線,所以它可以隨時向對端傳送資料包,再加上UDP本身的處理既簡單右高效,所以UDP經常用於如下幾個方面:

資料包總量比較少的通訊,比如DNS、SNMP。
視訊、音訊等對實時性要求比較高的多媒體通訊。
廣播通訊、多播通訊。
2、TCP:
(1)TCP,控制傳輸協議,和UDP的差別很大,它充分實現了資料傳輸時的各種控制功能:

針對傳送端發出的資料包的確認應答訊號ACK、、、針對資料包丟失或者出現定時器超時的重發機制、、、針對資料包到達接收端主機順序亂掉的順序控制、針對高效傳輸資料包的流動視窗控制、、、針對避免網路擁堵時候的流量控制、、、針對剛開始啟動的時候避免一下子傳送大量資料包而導致網路癱瘓的慢啟動演算法和擁塞控制。

(2)而這些在UDP中都是沒有的!此外,TCP作為一種面向有連線的控制傳輸協議,只有在確認對端主機存在時才會傳送資料,從而可以控制通訊流量的浪費。

言歸正傳:TCP通過序列號、檢驗和、確認應答訊號、重發控制、連線管理、視窗控制、流量控制、擁塞控制實現可靠性。
1、通過序列號和確認應答訊號提高可靠性。
(1)如圖1 所示:在TCP中,當接收端主機接收到來自客戶端主機的資料包之後,接收端主機會返回一個已收到訊息的通知,這個通知訊息就叫做確認應答訊號ACK包。

(2)TCP通過肯定的確認應答訊號ACK包來實現可靠的資料傳輸。當傳送端將資料發出之後會等待對端的確認應答。如果有確認應答,說明資料已經成功到達對端主機了。反之,若沒有收到確認應答,則資料包丟失的可能性比較大。

(3)情況1:資料包丟失的情況:

如圖2 所示,在特定的等待時間間隔內傳送端主機還是沒有收到來自接收端的確認應答,傳送端就可以認為資料已經丟失了,並且進行重發處理。由此,即使產生了丟包也能夠保證資料到達對端,實現可靠傳輸。

(4)情況2:確認應答丟失的情況:

如圖3 所示,未收到對端的確認應答訊號並不一定意味著資料包的丟失,也有可能是因為對端主機已經收到了該資料包,但是針對該資料包的確認應答包在回送途中丟失了而已,或者沒有丟失、只是因為網路中的其他一些原因延遲很長時間才到達源主機。

此時,源主機只會按照重發機制重發資料包而已,但是這對於對端主機來說簡直就是災難,因為對端主機會反覆接收到很多重複的不必要的資料,而為了對上層應用協議提供可靠的傳輸,對端主機不得不丟掉這些重複的資料包。因此,這對網路擁塞的形成造成了很大的促進。

所以,需要一種機制來識別是否已經接收到了這個資料包、又能夠判斷資料包是否需要接收。

上述這些 確認應答處理、重發控制、重複處理 都可以使用資料包的序列號來進行實現。

如圖4 所示,序列號 是指按照順序給傳送資料包中的每一個位元組都標識上號碼編號,接收端主機 根據接收資料TCP包首部中的序列號和資料長度,來將自己下一步應該接收的序列號作為確認應答返送回去。就這樣,根據序列號和確認應答訊號,TCP可以實現可靠傳輸。

2、超時重發如何確定呢?
(1)重發超時,是指在傳送端主機在重發資料包之前,等待接收端主機的確認應答訊號到來的“那個特定的時間間隔”。

如果超過了這個特定的時間間隔仍未收到ACK包,傳送端則會進行重發。

(2)那這個特定的時間間隔如何確定呢? TCP為了保證在任何網路下都能夠提供比較高的傳輸效能,並且在任何網路下都能夠保持住這一特性,它在每次發包時都會計算往返時間及其偏差,將這個“往返時間+偏差”,重發超時就是比這個總和值要稍大一點的值。

(3)在Windows系統中,超時時間都是以0.5s 為單位進行控制的,因此超時時間都是0.5s 的整數倍。不過由於最初的資料包還不知道往返時間,所以最初的重發超時時間一般設定為6s 左右。

另外,若是進行了重發處理,則第二次、第三次的等待的超時時間會以2倍、4倍的指數函式增長,以此類推。

但是,資料包也不會倍無限次的反覆的進行重發。當重發次數達到一定次數過之後,如果傳送端還是接收不到對端主機的ACK包,那麼傳送端主機就會認為網路或者對端主機出現了異常,進行強制關閉連線,並且通知應用程式異常強制終止。

3、TCP的連線管理。
(1)TCP是面向有連線的資料通訊,也就說在進行實際的資料包的收發之前,會先做好通訊兩端主機的準備工作:TCP三次握手!

    見部落格:20170906_我是如何講清楚TCP的三次握手和四次揮手的

(2)在雙端主機進行資料的互動完成過之後,會進行TCP連線的斷開處理。見上面的部落格。

4、TCP是以段為單位進行資料包的傳送的。
(1)在建立TCP連線的同時,也可以確定傳送資料包的單位,稱之為“最大訊息長度”:MSS。最理想的情況是,最大訊息長度MSS正好是IP層中不被分片處理的最大資料長度。

(2)TCP在傳送大量資料的時候,是以“段=MSS的大小”將資料進行分割傳送的,進行重發時也是以MSS為單位的。

(3)如圖5 所示:最大訊息長度——MSS是在三次握手的時候,在兩端主機之間被計算得出的。兩端主機在發出“建立TCP連線請求的SYN包”時,會在SYN包的TCP首部中寫入MSS選項,告訴對方自己所能夠適應的MSS的大小,然後傳送端主機會在兩者之間選擇一個較小的MSS值投入使用。

5、利用滑動視窗控制提高速度。
(1)如圖6 所示:TCP是以一個段為單位進行資料的傳輸的,每傳送一個段,就會等待對端主機的針對這個段的確認應答訊號ACK,但這樣的傳輸方式的缺點也很明顯,就是:當資料包的往返時間越長,通訊效能越低。

(2)為了解決這個問題,TCP引入了視窗這個概念,即使在往返時間比較長的情況下,它也能夠控制網路效能的下降。如圖7 所示:確認應答包不再以每個段為單位進行確認了,而是以更大的單位進行確認,轉發時間將會被大幅度的縮短。也就是說,傳送端主機在傳送了一個段之後,沒必要一直等待對端主機的確認應答訊號,而是繼續傳送。

(3)視窗大小,指的就是無需等待接收端主機的確認應答訊號而可以持續傳送的資料的最大值,或者說段的最大值,比如圖7 所示的視窗大小是4 個段。  滑動視窗控制的實現,使用了大量的緩衝區,通過對多個段的資料同時進行確認應答來實現高效傳輸。

(4)如圖8 所示,傳送資料中的高亮部分正是前面提到的視窗。在這個視窗內的資料即便沒有收到確認應答也可以傳送出去,此外發送端主機在等到對端主機的確認應答之前,必須在緩衝區中保留這部分資料,以便資料包的丟失而重發。

(5)在滑動視窗以外的資料,包括尚未傳送出去的資料,以及已經確認對端收到的資料,當傳送端確認對端已經收到資料包之後,此資料包就可以從緩衝區中清除了。

當收到確認應答訊號過之後,會把滑動視窗的位置滑動到確認應答的序列號的位置,這樣就可以順序的將多個段同時傳送以提高通訊功能了。這就是滑動視窗控制。

6、滑動視窗控制與重發控制。

(1)在使用了視窗控制中,如果出現了丟包怎麼辦呢?

首先,我們先考慮接收端已經收到資料包只是反饋的確認應答包ACK包在途中丟失了的情況。

如圖9 所示:在這種情況下,資料是已經被對端主機成功接收了的,是不需要進行重新發送的。然而,在沒有使用視窗控制的前提下,沒有收到確認應答包的資料包都會被重發。但是,在使用了視窗控制以後,就如圖9 所示,某些應答包即使丟失了也無需重發,這也提高了傳輸效率。

(2)其次,我們再來考慮一下某個資料包丟失的情況。

如果當接收端主機接收到一個自己應該接收的序列號之外的資料包時,它會一直對當前接收到的資料包返回確認應答包。

因此,如圖10 所示:當某一個數據包丟失以後,傳送端會一直接收到序列號為1001的確認應答包,這個確認應答包好像是在提醒傳送端主機“我現在想要接收的資料包序列號是1001開始的”。

因此,在滑動視窗比較大的情況下,同一個序列號的確認應答將會被重複不斷地返回。而傳送端主機如果 連續 3 次 接收到同一個確認應答包,就會將其對應的資料重發,這種機制比之前提到的“超時重發”更加高效,所以被稱之為“高速重發控制”。

7、流量控制。
(1)傳送端主機會根據自己的實際情況傳送資料,而接收端也會跟據自己的實際情況接收資料。因此,TCP協議提供了這樣一種機制:可以讓傳送端主機根據接收端主機的實際接收能力來控制自己傳送的資料量。這就是所謂的“流控制”。

(2)具體操作就是:接收端主機向傳送端主機通知自己所能夠接收資料的大小,於是傳送端主機就會發送不超過這個限度的資料,該大小被稱之為“通告視窗”,就是之前提到的“控制視窗”,這個值是由接收端主機決定的。

TCP首部中,專門有一個欄位用來通知“視窗大小”,接收端主機可以將自己的實際接收緩衝區大小寫入到這個欄位中通知給傳送端,這個值越大說明網路的吞吐量越大。

不過,接收端主機的緩衝區一旦面臨資料溢位,就會主動減小視窗的大小再次傳送給傳送端主機,從而可以控制資料傳送量。也就是說,傳送端主機會根據接收端主機的指示,對傳送的資料量進行控制,這也就形成了一條完整的TCP流量控制。

(3)如圖11 所示:當接收端主機收到了從3001號開始的資料包之後其緩衝區即將滿,不得不暫時停止接收資料,於是把視窗大小設定為0,然後通知該傳送端。之後,傳送端在收到新的視窗更新值的通知之後通訊才得以繼續進行。

如果這個滑動視窗的更新通知在傳輸途中丟失了,則很有可能導致無法繼續進行通訊。為了避免此種問題的發生,傳送端主機會時不時的傳送一個叫做“探測視窗”的資料包,次資料包僅含有一個位元組,以獲取最新的視窗大小。

8、擁塞控制。
(1)有了TCP的滑動視窗控制,收發主機之間即使不再以一個“段”為單位傳送確認應答訊號,也能夠連續傳送大量資料包。然而,如果在通訊剛開始的時候就傳送大量的資料包,也有可能會導致其他問題。

問題的發生: 要知道,計算機網路都處在一個共享的環境中,因此也有可能是因為其他的主機之間的通訊使得整個網路出現擁堵。所以,在網路擁堵時,如果突然傳送一個較大量的資料包,極有可能導致網路的癱瘓。

(2)TCP為了防止這種問題的發生,在通訊一開始的時候會通過一個叫做“慢啟動”的演算法對傳送的資料量進行控制。

首先,為了在傳送端調節所要傳送的資料量,定義了一個叫做“擁塞視窗”的概念。於是,在慢啟動剛開始的時候,把這個擁塞視窗設定為1個MSS(1個數據段)傳送資料,之後每收到一個接收端主機的確認應答訊號ACK包 就把這個擁塞視窗的數值加1。然後,在傳送資料的時候,把擁塞視窗和滑動視窗的大小作比較,按照它們當中較小的那個值來發送比其還要小的資料量。

不過,隨著資料包的每次的往返,擁塞視窗會以1、2、4、8等指數函式的增長,擁堵狀況激增甚至導致網路擁塞的發生。為了防止這些,又引入了“慢啟動閾值”的概念,只要擁塞視窗超過這個閾值,在每收到一個ACK包的時候,只允許以下面這種方式來增大擁塞視窗:(1個數據段的位元組數的平方 / 擁塞視窗的位元組數)。這樣的話,擁塞視窗越大,確認應答的數目也會增加,但是其漲幅卻逐漸減少,因此會導致擁塞視窗是直線形式的上升。

TCP在剛開始通訊的時候,並沒有設定慢啟動閾值,而是在超時重發時,才會把慢啟動閾值設定為當前視窗的一半大小。

(3)由重複確認應答而觸發的高速重發與超時重發機制的處理是不一樣的。因為前者要求至少 3 次的確認應答包到達對方主機才會觸發,相比後者網路擁堵的程度較輕一些。

而由重複確認應答進行高速重發控制時,慢啟動閾值的大小被設定為當時視窗大小的一半,然後將視窗大小設定為該慢啟動閾值+3個MSS的大小。

(4)有了這樣的一種控制過之後,TCP的擁塞視窗的變化曲線 如圖12 所示。由於視窗的大小會直接影響資料被轉發的吞吐量,所以一般情況下,視窗越大,越會形成高吞吐量的通訊。

9、納格演算法:Nagle演算法。
(1) TCP/IP協議中,無論傳送多少資料,總是要在資料前面加上協議頭。同時,對方接收到資料,也需要傳送ACK表示確認。
 為了儘可能的利用網路頻寬,TCP總是希望儘可能的傳送足夠大的資料。(一個連線會設定MSS引數,因此,TCP/IP 希望每次都能夠以MSS尺寸的資料塊來發送資料)。

(2) Nagle演算法就是為了儘可能傳送大塊資料,避免網路中充斥著許多小資料塊。 Nagle演算法的基本定義是:在任意時刻,最多隻能有一個未被確認的小段。 

所謂“小段”,指的是小於MSS尺寸的資料塊。所謂“未被確認”,是指一個數據塊傳送出去後,沒有收到對方傳送的ACK確認該資料已收到。

(3)這是因為TCP/IP 中不僅僅有Nagle演算法,還有一個TCP確認延遲機制 。當Server端收到資料之後,它並不會馬上向client端傳送ACK,而是會將ACK的傳送延遲一段時間(假設為 t),
它希望在 t 時間內server端會向client端傳送應答資料,這樣ACK就能夠和應答資料一起傳送,就像是應答資料捎帶著ACK過去。


--------------------- 
作者:stormchenmeng 
來源:CSDN 
原文:https://blog.csdn.net/cmm0401/article/details/77878998 
版權宣告:本文為博主原創文章,轉載請附上博文連結!