1. 程式人生 > >TCP可靠性的保證機制總結

TCP可靠性的保證機制總結

TCP保證可靠性主要依靠下面7種機制:
1、檢驗和
TCP檢驗和的計算與UDP一樣,在計算時要加上12byte的偽首部,檢驗範圍包括TCP首部及資料部分,但是UDP的檢驗和欄位為可選的,而TCP中是必須有的。計算方法為:在傳送方將整個報文段分為多個16位的段,然後將所有段進行反碼相加,將結果存放在檢驗和欄位中,接收方用相同的方法進行計算,如最終結果為檢驗欄位所有位是全1則正確(UDP中為0是正確),否則存在錯誤。
2、序列號
TCP將每個位元組的資料都進行了編號,這就是序列號。
序列號的作用:
a、保證可靠性(當接收到的資料總少了某個序號的資料時,能馬上知道)
b、保證資料的按序到達
c、提高效率,可實現多次傳送,一次確認
d、去除重複資料
資料傳輸過程中的確認應答處理、重發控制以及重複控制等功能都可以通過序列號來實現
3、確認應答機制(ACK)
TCP通過確認應答機制實現可靠的資料傳輸。在TCP的首部中有一個標誌位——ACK,此標誌位表示確認號是否有效。接收方對於按序到達的資料會進行確認,當標誌位ACK=1時確認首部的確認欄位有效。進行確認時,確認欄位值表示這個值之前的資料都已經按序到達了。而傳送方如果收到了已傳送的資料的確認報文,則繼續傳輸下一部分資料;而如果等待了一定時間還沒有收到確認報文就會啟動重傳機制。
正常情況下的應答機制:
這裡寫圖片描述


4、超時重傳機制
當報文發出後在一定的時間內未收到接收方的確認,傳送方就會進行重傳(通常是在發出報文段後設定一個鬧鐘,到點了還沒有收到應答則進行重傳),其基本過程如下:
這裡寫圖片描述
當然,未收到確認不一定就是傳送的資料包丟了,還可能是確認的ACK丟了:
這裡寫圖片描述
當接收方接收到重複的資料時就將其丟掉,重新發送ACK。而要識別出重複的資料,就要用到前面提到的序列號了,利用序列號很容易就可以做到去重的效果。
重傳時間的確定:報文段發出到收到應答中間有一個報文段的往返時間RTT,顯然超時重傳時間RTO會略大於這個RTT,TCP會根據網路情況動態的計算RTT,即RTO是不斷變化的。在Linux中,超時以500ms為單位進行控制,每次判定超時重發的超時時間都是500ms的整數倍。其規律為:如果重發一次仍得不到應答,就等待2*500ms後再進行重傳,如果仍然得不到應答就等待4*500ms後重傳,依次類推,以指數形式遞增,重傳次數累計到一定次數後,TCP認為網路或對端主機出現異常,就會強行關閉連線。

5、連線管理機制
連線管理機制即TCP建立連線時的三次握手和斷開連線時的四次揮手。
首先三次握手:
這裡寫圖片描述
建立過程為:
(1)B首先建立傳輸控制塊TCB,進入LISTEN(收聽)狀態,等待使用者的連線請求。如有,則建立連線。(這個過程在套接字程式設計中為伺服器端呼叫socket函式、bind函式和listen函式的過程)
(2)A建立傳輸控制塊TCB,然後向B傳送連線請求報文段,報文段中首部的同步位SYN=1,同時選擇一個序列號seq=x,TCP規定SYN報文段不攜帶資料,但要消耗一個序列號。然後A進入SYN-SENT(同步已傳送)狀態。(這個過程在套接字程式設計中為客戶端呼叫socket函式和connect函式的過程)
(3)B收到請求後,如同意建立連線,就向A傳送確認報文段。此時SYN=1、ACK=1,確認號ack=x+1,同時選擇一個序列號seq=y,這個報文也不攜帶資料,但要消耗一個序列號。然後B進入SYN-RCVD狀態(同步收到)。
(4)A收到B的確認後,還要向B傳送確認。確認報文段的ACK=1,確認號ack=y+1,seq=x+1。TCP規定,ACK報文段可以攜帶資料,而如果不攜帶資料則不消耗序列號,此時下一個報文段的序列號仍為seq=x+1。這時,連線就建立成功了,A進入ESTABLISHED狀態(已建立連線狀態)。
(5)當B收到A的確認後,也進入ESTABLISHED狀態,此時就可以進行資料傳輸了。
當然,在進行三次握手時不是僅進行連線,可能還會進行一些後續操作所需要的資訊交流。

四次揮手:
這裡寫圖片描述
在連線釋放時,連線的兩方都要同意才能夠釋放成功(就像情侶分手一樣,分手時兩個人的事兒)。連線的雙方都可以提出釋放連線,這裡假設A先提出釋放連線,首先雙方都處於ESTABLISHED狀態。
(1)當A的資料傳送完後,就可以向其TCP發起連線釋放了,此後停止再發送資料,主動關閉TCP連線。首先A向B傳送一個FIN報文段,報文段首部FIN=1,序列號seq=u(u為最後傳送的資料的序列號加1),然後A進入FIN-WAIT-1(終止等待1)狀態。FIN報文段不能攜帶資料,但要消耗一個序列號。
(2)B收到釋放連線的報文段後即發出確認報文段,報文首部ACK=1,ack=u+1,seq=v(v等於B前面傳送過的資料的序列號加1),然後B進入CLOSE-WAIT(關閉等待)狀態。這時從A到B這個方向的連線就釋放了,TCP連線就處於半關閉狀態。(注意:此後A不能主動向B傳送資料,但是A可以給B傳送確認報文段,也就是說A仍要接收來自B的報文,因為從B到A這個方向的連線還沒有關閉)
(3)當A收到B的確認報文後,就進入FIN-WAIT-2(終止等待2)狀態,等待B發出的連線釋放報文段。
(4)當B的資料傳送完畢後,其應用程序就通知TCP釋放連線。B向A傳送FIN報文,報文段首部FIN=1,ack=u+1(重複傳送上一次已經發送過的確認號),seq=w(w為B最後傳送報文段的序列號加1)。然後B進入LAST-ACK(最後確認)狀態,等待A的確認。
(5)A在接收到B的連線釋放報文後,必須進行確認。A向B傳送的確認報文段中報文首部ACK=1,ack=w+1,seq=u+1。然後A進入TIME-WAIT(時間等待)狀態(如果無差錯,此狀態時間為2MSL),注意,此時TCP連線還沒有釋放掉,必須經過TIME-WAIT設定的時間2MSL後,A撤銷相應的傳輸控制塊TCB,才進入CLOSED狀態,結束了此次TCP連線。MSL叫做最長報文段壽命,RFC793建議設為2分鐘,但在現在實際網路情況中,常用值有三種:30秒,1分鐘,2分鐘。必須要在A進入CLOSED狀態後才能開始建立下一個新的連線。
(6)B收到A的確認報文後,也進入CLOSED狀態,撤銷相應的傳輸控制塊TCB,此時,TCP連線全部斷開。
這樣TCP四次揮手完成。

6、流量控制
接收端處理資料的速度是有限的,如果傳送方傳送資料的速度過快,導致接收端的緩衝區滿,而傳送方繼續傳送,就會造成丟包,繼而引起丟包重傳等一系列連鎖反應。
因此TCP支援根據接收端的處理能力,來決定傳送端的傳送速度,這個機制叫做流量控制。
在TCP報文段首部中有一個16位視窗長度,當接收端接收到傳送方的資料後,在應答報文ACK中就將自身緩衝區的剩餘大小,放入16視窗大小中。這個大小隨資料傳輸情況而變,視窗越大,網路吞吐量越高,而一旦接收方發現自身的緩衝區快滿了,就將視窗設定為更小的值通知傳送方。如果緩衝區滿,就將視窗置為0,傳送方收到後就不再發送資料,但是需要定期傳送一個視窗探測資料段,使接收端把視窗大小告訴傳送端。
其過程如下:
這裡寫圖片描述
注意:視窗大小不受16位視窗大小限制,在TCP首部40位元組選項中還包含一個視窗擴大因子M,實際視窗大小是視窗欄位的值左移M位。

7、擁塞控制
流量控制解決了 兩臺主機之間因傳送速率而可能引起的丟包問題,在一方面保證了TCP資料傳送的可靠性。然而如果網路非常擁堵,此時再發送資料就會加重網路負擔,那麼傳送的資料段很可能超過了最大生存時間也沒有到達接收方,就會產生丟包問題。
為此TCP引入慢啟動機制,先發出少量資料,就像探路一樣,先摸清當前的網路擁堵狀態後,再決定按照多大的速度傳送資料。
此處引入一個擁塞視窗:
傳送開始時定義擁塞視窗大小為1;每次收到一個ACK應答,擁塞視窗加1;而在每次傳送資料時,傳送視窗取擁塞視窗與接送段接收視窗最小者。
慢啟動:在啟動初期以指數增長方式增長;設定一個慢啟動的閾值,當以指數增長達到閾值時就停止指數增長,按照線性增長方式增加;線性增長達到網路擁塞時立即“乘法減小”,擁塞視窗置回1,進行新一輪的“慢啟動”,同時新一輪的閾值變為原來的一半。
“慢啟動”機制可用圖表示:
這裡寫圖片描述
文中可能有不少錯誤,望各位高手指正。