當前位置:編程學習大全網 - 源碼下載 - TCP 詳解

TCP 詳解

title: TCP 總結

date: 2018-03-25 09:40:24

tags:

categories:

-計算機網絡

?我們都知道 TCP 是位於傳輸層的協議,他還有壹個兄弟就是 UDP ,他們兩***同構成了傳輸層。顯然他們之間有很大的區別要不然的話在傳輸層只需要壹個就好了。

?其中最重要的區別就是壹個面向連接另外壹個不是,這個區別就導致了他們是否能夠保證穩定傳輸,顯然不面向連接的 UDP 是沒辦法保證可靠傳輸的,他只能靠底層的網絡層和鏈路層來保證。我們都知道網絡層采用的是不可靠的 IP 協議。好吧,網絡層也保證不了可靠傳輸,所以 UDP 保證可靠傳輸只能依靠鏈路層了。

?而 TCP 就好說了他不僅僅有底層的鏈路層的支持,還有自己的面向鏈接服務來保證可靠傳輸。當然 TCP也不僅僅就是比 UDP 多了壹個可靠傳輸,前面也說到了這只是他們之間壹個重要的區別。其實他的三個重要特性就是它們之間的區別。

?* 可靠傳輸

?* 流量控制

?* 擁塞控制

TCP 主要是 確認重傳機制 數據校驗 數據合理分片和排序 流量控制 擁塞控制 依靠來完成可靠傳輸的 , 下面詳細介紹這幾種保證可靠傳輸的方式。

確認重傳,簡單來說就是接收方收到報文以後給發送方壹個 ACK 回復,說明自己已經收到了發送方發過來的數據。如果發送方等待了壹個特定的時間還沒有收到接收方的 ACK 他就認為數據包丟了,接收方沒有收到就會重發這個數據包。

好的,上面的機制還是比較好理解的,但是我們會發現壹個問題,那就是如果接收方已經收到了數據然後返回的 ACK 丟失,發送方就會誤判導致重發。而此時接收方就會收到冗余的數據,但是接收方怎麽能判定這個數據是冗余的還是新的數據呢?

這就涉及到了 TCP 的另外壹個機制就是采用序號和確認號,也就是每次發送數據的時候這個報文段裏面包括了當前報文段的序號和對上面的報文的確認號,這樣我們的接收方可以根據自己接受緩存中已經有的數據來確定是否接受到了重復的報文段。這時候如果出現上面所說的 ACK 丟失,導致接受重復的報文段時客戶端丟棄這個冗余的報文段。

好現在我們大致了解了確認重傳機制,但是還有些東西還沒有弄清楚,也就是 TCP 真正的實現究竟是怎樣的。

這就是我們要解決的第壹個問題就是如何確認。這裏涉及到兩種確認方式,分別稱為 累計確認(捎帶確認) 和 單停等協議 。

用壹張圖來快速理解,就是每發送壹次數據,就進行壹次確認。等發送方收到了 ACK 才能進行下壹次的發送。

壹樣的也是采用的 ACK 機制,但是註意壹點的是,並非對於每壹個報文段都進行確認,而僅僅對最後壹個報文段確認,捎帶的確認了上圖中的 203 號及以前的報文。

<font color=#A52A2A>

總結:從上面可以看到累計確認的效率更加高,首先他的確認包少壹些那麽也就是在網絡中出現的大部分是需要傳輸的數據,而不是壹半的數據壹半的 ACK ,然後我們在第二張圖中可以看到我們是可以連續發送多個報文段的(究竟壹次性能發多少這個取決於發送窗口,而發送窗口又是由接受窗口和擁塞窗口壹起來決定的。),壹次性發多個數據會提高網絡的吞吐量以及效率這個可以證明,比較簡單這裏不再贅述!

結論:顯然怎麽看都是後者比較有優勢,TCP 的實現者自然也是采用的累計確認的方式!

</font>

上文中的那個特定的時間就是超時時間,為什麽有這個值呢? 其實在發送端發送的時候就為數據啟動了壹個定時器,這個定時器的初始值就是超時時間。

超時時間的計算其實有點麻煩,主要是我們很難確定壹個確定的值,太長則進行了無意義的等待,太短就會導致冗余的包。TCP 的設計者們設計了壹個計算超時時間的公式,這個公式概念比較多,有壹點點麻煩,不過沒關系我們壹點點的來。

首先我們自己思考如何設計壹個超時時間的計算公式,超時時間壹般肯定是和數據的傳輸時間有關系的,他必然要大於數據的往返時間(數據在發送端接收端往返壹趟所用的時間)。好,那麽我們就從往返時間下手,可是又有壹個問題就是往返時間並不是固定的我們有如何確定這個值呢?自然我們會想到我們可以取壹小段時間的往返時間的平均值來代表這壹時間點的往返時間,也就是微積分的思想!

好了我們找到了往返時間(RTT),接下來的超時時間應該就是往返時間再加上壹個數就能得到超時時間了。這個數也應該是動態的,我們就選定為往返時間的波動差值,也就是相鄰兩個往返時間的差。

下面給出我們所預估的超時時間(TimeOut)公式:

很好,看到這裏其實妳已經差不多理解了超時時間的計算方式了,只不過我們這個公式不夠完善,但是思路是對的。我們這時候來看看 TCP 的實現者們采用的方式。

好的,這就是 TCP 實現的超時時間的方式,但是在實際的應用中並不是壹直采用的這種方式。假如說我們現在網絡狀態非常的差,壹直在丟包我們根本沒必要這樣計算,而是采用直接把原來的超時時間加倍作為新的超時時間。

<font color=#A52A2A>

總結:好的現在我們知道了在兩種情況下的超時時間的計算方式,正常的情況下我們采用的上面的比較復雜的計算公式,也就是 RTT+波動值 否則直接加倍

</font>

上面我們看到在發送方等待壹個超時重傳時間後會開始重傳,但是我們計算的超時重傳時間也不定就很準,也就是說我們經常幹的壹件事就會是等待,而且壹般等的時間還挺長。那麽可不可以優化壹下呢?

當然,在 TCP 實現中是做了優化的,也就是這裏說到的快速重傳機制。他的原理就是在發送方收到三個冗余的 ACK 的時候,就開始重傳那個報文段。那麽為什麽是三個冗余的 ACK 呢?註意三個冗余的 ACK 其實是四個 ACK 。我們先了解壹下發送 ACK 策略,這個是 RFC 5681 文檔 規定的。

好的,那麽現在我們可以看到如果出現了三個冗余的 ACK 他只可能是發生了兩次情況三,也就是發送了兩個比期望值大的數據。但是註意出現情況三有兩種可能,壹個是丟包,另外壹個是亂序到達。

比如說我們現在是數據亂序到達的,我們來看壹下。

第壹種亂序情況

另外壹種亂序

丟包情況

<font color=#A52A2A>

結論: 很顯然我們可以看到,如果發生了亂序有可能會出現三次冗余 ACK,但是如果發現了丟包必然會有三次冗余 ACK 發生,只是 ACK 數量可能更多但是不會比三次少

</font>

在我們發現丟包以後我們需要重傳,但是我們重傳的方式也有兩種方式可以選擇分別是 GBN 和 SR 翻譯過來就是 拉回重傳 和 選擇重傳 。好其實我們已經能從名字上面看出來他們的作用方式了,拉回重傳就是哪個地方沒收到那麽就從那個地方及以後的數據都重新傳輸,這個實現起來確實很簡單,就是把發送窗口和接受窗口移回去,但是同樣的我們發現這個方式不實用幹了很多重復的事,效率低。

那麽選擇重傳就是妳想到的誰丟了,就傳誰。不存在做無用功的情況。

<font color=#A52A2A>

結論: TCP 實際上使用的是兩者的結合,稱為選擇確認,也就是允許 TCP 接收方有選擇的確認失序的報文段,而不是累計確認最後壹個正確接受的有序報文段。也就是跳過重傳那些已經正確接受的亂序報文段。

</font>

?數據校驗,其實這個比較簡單就是頭部的壹個校驗,然後進行數據校驗的時候計算壹遍 checkSum 比對壹下。

?在 UDP 中,UDP 是直接把應用層的數據往對方的端口上 “扔” ,他基本沒有任何的處理。所以說他發給網絡層的數據如果大於1500字節,也就是大於MTU。這個時候發送方 IP 層就需要分片。把數據報分成若幹片,使每壹片都小於MTU.而接收方IP層則需要進行數據報的重組。這樣就會多做許多事情,而更嚴重的是 ,由於UDP的特性,當某壹片數據傳送中丟失時 , 接收方便無法重組數據報,將導致丟棄整個UDP數據報。

?而在 TCP 中會按MTU合理分片,也就是在 TCP 中有壹個概念叫做最大報文段長度(MSS)它規定了 TCP 的報文段的最大長度,註意這個不包括 TCP 的頭,也就是他的典型值就是 1460 個字節(TCP 和 IP 的頭各占用了 20 字節)。並且由於 TCP 是有序號和確認號的,接收方會緩存未按序到達的數據,根據序號重新排序報文段後再交給應用層。

?流量控制壹般指的就是在接收方接受報文段的時候,應用層的上層程序可能在忙於做壹些其他的事情,沒有時間處理緩存中的數據,如果發送方在發送的時候不控制它的速度很有可能導致接受緩存溢出,導致數據丟失。

?相對的還有壹種情況是由於兩臺主機之間的網絡比較擁塞,如果發送方還是以壹個比較快的速度發送的話就可能導致大量的丟包,這個時候也需要發送方降低發送的速度。

?雖然看起來上面的兩種情況都是由於可能導致數據丟失而讓發送主機降低發送速度,但是壹定要把這兩種情況分開,因為前者是屬於 流量控制 而後者是 擁塞控制 ,那將是我們後面需要討論的事情。不要把這兩個概念混了。

?其實說到流量控制我們就不得不提壹下滑動窗口協議,這個是流量控制的基礎。由於 TCP 連接是壹個全雙工的也就是在發送的時候也是可以接受的,所以在發送端和接收端同時維持了發送窗口和接收窗口。這裏為了方便討論我們就按照單方向來討論。

?接收方維持壹個接受窗口,發送方壹個發送窗口。發送的時候要知道接受窗口還有多少空間,也就是發送的數據量不能超過接受窗口的大小,否則就溢出了。而當我們收到壹個接收方的 ACK 的時候我們就可以移動接受窗口把那些已經確認的數據滑動到窗口之外,發送窗口同理把確認的移出去。這樣壹直維持兩個窗口大小,當接收方不能在接受數據的時候就把自己的窗口大小調整為 0 發送窗口就不會發送數據了。但是有壹個問題,這個時候當接收窗口再調大的時候他不會主動通知發送方,這裏采用的是發送方主動詢問。

?還是畫個圖看的比較直觀:

?擁塞控制壹般都是由於網絡中的主機發送的數據太多導致的擁塞,壹般擁塞的都是壹些負載比較高的路由,這時候為了獲得更好的數據傳輸穩定性,我們必須采用擁塞控制,當然也為了減輕路由的負載防止崩潰。

?這裏主要介紹兩個擁塞控制的方法,壹個是慢開始,另外壹個稱為快恢復。

那麽問題來了,為什麽需要序號呢?為什麽又是三次握手而不是兩次?以及什麽是 SYN 洪泛攻擊?

這裏需要說明壹下的是最後的那個長長的 TIME_WAIT 狀態壹般是為了客戶端能夠發出 ACK 壹般他的值是 1分鐘 或者2分鐘

?好了,今天真的寫了不少,主要就是把 TCP 的可靠傳輸以及連接管理講清楚了,以及裏面的壹下細節問題,真的很花時間。然後其他沒有涉及到的就是關於 TCP 的頭並沒有詳細的去分析,這個東西其實也不是很難,但是現在篇幅真的已經很大就先這樣,頭裏面的都是固定的不需要太多的理解。

  • 上一篇:gitpython如何修改文件內容不影響格式
  • 下一篇:冒險島被洗了怎麽辦?
  • copyright 2024編程學習大全網