深入理解TCP

2021-08-20 06:24:42 字數 4206 閱讀 2868

tcp是面向連線的傳輸層層協議,可以為應用層提供可靠的資料傳輸服務。所謂的面向連線並不是真正意思上的連線,只不過是在傳送資料之前,首先得相互握手,也就是說接收方知道你要發資料給它了。而udp是面向無連線的傳輸層協議,並不提供可靠的資料傳輸。有乙個很恰當的比喻:udp傳輸就類似於寫信,接收方事先並不知道你要寫信給他;而tcp傳輸就像是打**,必須等對方按了接聽鍵你才能更他通話。

那麼tcp又是如何來實現面向連線和可靠性服務的??在討論tcp的可靠資料傳輸之前,我們先看看最簡單的傳輸層服務udp。

1、udp

源埠號/目的埠號:同tcp首部中埠號的作用相同

首部長度:報文段中的位元組數(首部加資料)。

校驗和:差錯檢測,用於確定當udp報文段從源到達目地移動時,其中的位元是否發生了變化。

檢驗和如何計算??

包括三部分:udp偽首部、udp首部、udp資料部分。偽首部如下所示:

其中,協議字段:tcp為6,udp為17,udp長度即為udp(包括udp頭和資料部分)的總長度。

將所有字相加得到的結果為乙個16位的數,將該數取反即為檢驗和字段 

從udp的首部我們就可以看到,udp是乙個很簡陋的傳輸層協議,只負責從傳送端的應用層接收資料,封裝層udp報文段,然後交給下層傳送到接收端;在接收端,udp從下層接收資料,然後送達應用層。在該傳輸過程中,udp之提供乙個基本的差錯檢測服務,如果檢測沒有錯誤,就直接交給應用層;否則直接丟棄。

下面我們來看一下tcp提供的可靠傳輸服務:

2、tcp

源埠號/目的埠號:用於多路復用/分解來自或送到上層應用的資料。什麼意思呢?處於應用層的程序可能有很多,每個程序都有可能通過傳輸層傳送資料到網際網路或者通過傳輸層從網際網路中接收資料。那麼當傳輸層從網際網路中接收到資料應該傳送給應用層中的哪個程序?或者如何知道從應用層收到的資料是屬於應用層中的哪個服務??其實這些的實現都是通過埠號的標識的。應用層中的每個網路服務都對應著乙個埠號,通過埠號來標識對應的服務。所以說埠號是將傳輸層繫結到應用層的粘合劑。

序號和確認號:被用來實現可靠資料傳輸服務。

接收視窗字段:指示接收方接收緩衝區剩餘大小,用於流量控制。

首部長度字段:tcp首部中有乙個選項欄位的存在,也就是說tcp首部的長度是可變的,所以需要指明首部的長度。

選項字段:用於傳送方與接收方協商最大報文段長度(mss)時,或在高速網路環境下用作視窗調節因子時使用。還定義了乙個時間戳選項。

rst、syn、fin位元:用於連線的建立和拆除。

psh位元:當psh位元被設定時,表明接收方應該立即將資料交給上層。

urg位元和緊急資料指標:urg位元指示報文段裡存在著被傳送端的上層實體置為「緊急」的資料;緊急資料的最後乙個位元組由16bit的緊急資料指標字段指出。當緊急資料存在並給出緊急資料尾的時候,tcp必須立即通知接收端的上層實體。

檢驗和字段:同udp檢驗和,提供差錯檢測。

tcp 如何保證資料傳輸的可靠性??

(1) 在傳送資料之前,進行三次握手,保證與接收端相互可靠通訊。下面來講乙個三次握手的過程:

初始狀態客戶端和伺服器都為closed狀態,伺服器開啟listen監聽客戶連線進入listen狀態;然後客戶端傳送乙個syn包,序列號為j,此時客戶端進入syn_sent狀態;當伺服器接收到syn包時,伺服器進入syn_recv狀態,並且傳送乙個帶syn的ack,確認號為j+1,序列號為k;當客戶端收到這個帶syn的ack時,客戶端進入established狀態,對於客戶端來說,已經確認可以與伺服器通訊了,所以客戶端就可以發資料給伺服器了,此時客戶端發乙個ack(ack中可以包含資料資訊)到伺服器,確認號為k+1;在伺服器接收到ack之前,三次握手還沒有完成,雖然客戶端可以發資料給伺服器,但是只能包含在ack中,而伺服器並不能發資料到客戶端,只有當收到ack後,伺服器端進入狀態established狀態。自此,三次握手完成,客戶端可以與伺服器端已經建立了連線,可以互相傳送資料。

一定要進行三次握手麼,不能只進行兩次或者四次??

其實這個問題的本質是網際網路中通道不可靠, 但是要在這個不可靠的通道上可靠地傳輸資料,三次握手是最小的理論值。

如果只進行兩次握手,那麼當客戶端傳送乙個syn分組後,會發生兩種情況:

情況一:伺服器接收到了這個syn並返回ack,無論客戶端是否接收到了ack,伺服器都認為已經與客戶端建立連線了,於是就開始向客戶端傳送資料。但是如果客戶段沒有收到ack,那麼客戶端會認為與伺服器沒有建立連線,就不會接收伺服器發來的資料,也就是說直接丟棄伺服器發來的資料,伺服器發出的訊息超時了,就重**送資料,這就產生了死鎖。

情況二:客戶端發出的第乙個連線請求報文段並沒有丟失,而是在某個網路結點長時間的滯留了,以致延誤到連線釋放以後的某個時間才到達伺服器。本來這是乙個早已失效的報文段。但伺服器收到此失效的連線請求報文段後,就誤認為是客戶端再次發出的乙個新的連線請求。於是就向客戶端傳送ack,但是此時客戶端沒有發出請求,所以並不會理睬這個ack,而伺服器又開始發資料給客戶端了,這時候,客戶端又把這些資料都丟棄了,而伺服器發出的訊息超時了,就重**送資料,也產生了死鎖。

(2) 通過確認和重傳機制來保證資料的完整性和按序交付

tcp把資料看成是無結構和有序的位元組流,所以上面所說的報文段的序列號是該報文段首位元組的位元組流編號,而報文段中的確認號是主機期望從客戶端收到的下乙個位元組的序號。我們來舉個例子:

假設tcp從應用層接收到3000個位元組長度的資料,而tcp最大報文長度mss為1460,那麼就要對資料進行分段,第一段資料為0~1459位元組,第二段為1460~2919位元組,第三段為2920~2999位元組,那麼這三個報文段的序列號分別為0、1460、2920。

假如伺服器端接收到客戶端發過來的第乙個報文段0~1459位元組,那麼它期望收到的下乙個位元組的序列號為1460,那麼在返回給客戶端的ack中確認號即為1460,然後伺服器又收到客戶端發來的2920~2999位元組的報文,但是未收到1460~2919位元組,那麼伺服器端繼續期望下乙個接收位元組為1460,所以返回的ack中的確認號依舊為1460。tcp只確認直到第乙個未收到位元組之前的位元組,所以tcp提供的是累積確認。接收方保留失序的位元組,同時等待缺少的位元組來填補間隔。

當然在如此錯綜複雜的網路中,即使三次握手建立連線了,也不可能每次傳送資料都能成功到達目的地。客戶端每次向網路中傳送乙個報文號,其實還會繼續快取該報文,指導收到伺服器端發過來的ack確認伺服器收到了該報文,然後才會丟棄。但是當傳送的報文段在網路中發生丟包了或者產生了位元出錯又或者伺服器返回的ack丟失了,那麼客戶端將都收不到ack。那麼怎麼辦?總不能一直等著吧?

客戶端通過乙個定時器超時機制來保證客戶端不會無限制地等待。也就是當傳送乙個報文段後,就啟動定時器,當發生超時了還未收到伺服器發來的ack時,客戶端就重新傳送該報文段。但是設定多長時間呢??從客戶端傳送乙個報文到接收到ack相當於乙個來回,我們用往返時間rtt來表示,設定的這個定時器時間至少得大於rtt吧。如果是ack丟失了,那麼伺服器如果收到了這個重發的報文,那麼資料不就重複了麼??伺服器通過序列號來保證資料的無冗餘,當伺服器收到了這個重複的資料報時,便知道客戶端沒有收到ack超時了,就直接把它丟棄,然後返回給客戶端乙個最新的ack。

(3) tcp提供了流量控制和擁塞控制

流量控制其實是乙個速度匹配服務,也就是說傳送方傳送資料的速率要與接收方應用程式讀取速率相匹配,以消除接收端緩衝區溢位的可能性。在tcp首部中有乙個字段叫做接收視窗字段,它就是用來通知傳送端伺服器上剩餘的緩衝區的大小(rwnd)的。

tcp提供的擁塞控制並不是網路輔助的擁塞控制,而是端到端的擁塞控制,因為ip層並不向端系統提供顯式的網路擁塞反饋。那麼tcp傳送方如何限制它的傳送速率?傳送方又如何知道路徑上是否擁塞?

上面提到當資料報在網路中丟失時就可能發生超時,而伺服器段可能收到冗餘的資料報,當然客戶端也不例外,也可能收到冗餘的ack。所以我們把丟包事件定義為:要麼出現超時,要麼收到來自接收端的3個冗餘的ack。當丟包事件發生了,客戶端就知道鏈路上存在擁塞。

傳送端維護著乙個擁塞視窗(cwnd),乙個傳送方的緩衝區中未被求確認的資料量不會超過cwnd和rwnd(流量控制中接收視窗字段,伺服器上剩餘的緩衝區的大小)的最小值。這個約束限制了傳送方未被確認的資料量,也就間接限制了傳送速率。

其實tcp是按照如下原則來設定傳送速率:

那麼問題又來了cwnd的值又該如何設定呢??

通過tcp擁塞控制演算法:慢啟動、擁塞避免、快速恢復。

TCP協議深入理解

tcp協議在能夠傳送資料之前就建立起了 連線 要實現這個連線,啟動tcp連線的那一方首先將傳送乙個syn資料報。這只是乙個不包含資料的資料報,然後,開啟syn標記。如果另一方同時在它收到syn標記的埠通話,它將發回乙個syn ack syn和ack標誌位都被開啟,並將ack 確認 編號字段設定為剛收...

TCP協議深入理解

任何一方都可以關閉乙個tcp連線,要求雙方傳送乙個fin訊號關閉自己的通訊頻道。一方可以在另一方之前關閉,或者雙方同時關閉tcp連線。因此,當一 方傳送乙個fin訊號時,另一方可傳送 fin ack 開始關閉自己一方的通訊並且確認收到了第乙個fin訊號。傳送第乙個fin訊號的人接下來再發 送乙個 f...

深入理解TCP三握四揮

面試中被問到不少次tcp的三握四揮,今天特意來做乙個總結 一些資料是很久前找的,忘了參考的鏈結了 首先來看一張圖 最初,客戶機a與伺服器b的tcp程序都處於 closed 狀態。然後由伺服器b先建立tcb 傳輸控制塊 進入到listen 狀態,準備隨時響應客戶請求 下面開始三握 a的tcp程序建立t...