1. 程式人生 > >TCP協議詳細介紹

TCP協議詳細介紹

在談TCP協議之前,我們有必要先了解UDP協議,UDP協議與TCP協議一樣,都是屬於傳輸層協議,那麼我們就來看看他們之間有什麼區別:

  1. 可靠傳輸vs不可靠傳輸:TCP傳輸屬於可靠性傳輸,那麼它就一定會有許多機制來保證傳輸的可靠性,即需要的開銷就更多;而UDP協議不保證可靠,並不是說它傳輸的資料有錯誤它也不會去管,而是通過16位校驗和檢測資料是否出錯,如果有錯,就會直接丟掉。但是,並不會返回任何錯誤資訊。
  2. 面向連線vs無連線:面向連線也是屬於TCP協議保證可靠性的機制的一種。UDP協議則是無連線,在知道對方的IP地址和埠號後,直接將資料傳送給對方。
  3. 面向位元組流vs面向資料報:這都是站在應用層的角度來談的,因為TCP有一系列機制來保證資料的按序到達,所以另一端接收到資料後會按序放到TCP的接收緩衝區,應用層在可以隨意讀取。而UDP並沒有這種機制,所以,傳送端一次傳送多大的資料,接收端也要一次讀完,這就是面向資料報。

UPD協議端格式: 
這裡寫圖片描述

欄位解釋:

  1. 16位源埠號:標識“自己”在這個主機使用的埠號
  2. 16位目的埠號:標識將來到對方後“我”要將資料交給上一層的“誰”, 因為應用層的協議太多,不能窮舉,所以這裡只要標識出哪一個程序就好了。
  3. 16位UDP長度:表示整個資料報(UDP首部+UDP資料)的最大長度(64K)
  4. 16位校驗和:為了驗證資料是否出錯,如果出錯,就會直接丟棄,不會通知應用層。

這裡只是大致的介紹了UDP協議的內容,重頭戲是TCP協議,在瞭解TCP協議之前,先來看看TCP協議段格式: 
這裡寫圖片描述
是不是發現要比UDP協議的報頭資訊複雜的多,這就是TCP為什麼能保證傳輸的可靠性。下面我們來一個一個介紹這些欄位的作用。

  1. 16位源埠號與16位目的埠號的作用與UDP中的一樣,表示從哪個程序來到哪個程序去。
  2. 32位序號和32位序號:在瞭解這兩個欄位之前,首先要知道,TCP協議在傳輸資料時,將每個位元組的資料都進行了編號,即序列號,在傳送資料時,會將此次資料的最大序列號填到32序號欄位中,接收端在接收到資料後,將這些資料按序放到接收緩衝區當中,然後,將最大序列號+1填到確認序號欄位當中發給對方,表示確認序號(假設位1001)之前的資料“我”都接收到了,下次應該傳送序列號比確認序號(1001)大的資料了。
  3. 4位首部長度:TCP首部長度最大15*4(位元組)=60位元組,其中標準長度為20位元組(不包含選項)
  4. 6位保留位:這裡不多作介紹。
  5. 6位標誌位: 
    1. URG:緊急指標標誌位 ,表示緊急指標是否有效
    2. ACK:確認標誌位,表示確認序號是否有效。
    3. PSH:提示接收端的應用程式立刻從TCP緩衝區中把資料拿走。
    4. RST:重置標誌位,表示對方要求重新建立連線。把攜帶該標誌位的稱為復位報文段
    5. SYN:同步標誌位,表示對方請求建立連線,把攜帶標誌位的稱為同步報文段。
    6. FIN:結束標誌位,通知對方“我”要關閉了,把攜帶該標誌位的稱為結束報文段。

6.16位視窗大小:我們都知道,TCP是有自己的緩衝區的,當傳送端傳送資料過快而接收端處理資料太慢時,接收端的TCP緩衝區中的資料就會越來越多,當達到緩衝區所能儲存資料的最大值時,這時,如果傳送端繼續傳送資料,就可能會造成資料的丟失,但是,我們要時時刻刻記住,TCP協議是保證可靠的,所以是不會允許這種事情發生的,16位視窗大小就是為了防止這樣的事情發生的,它是用來描述自己當前接收能力(接收緩衝區大小)的欄位。 
7.16位校驗和:傳送端填充,CRC校驗。接收端校驗不通過,則認為資料有問題。此處的校驗和不光包含TCP的首部,還包含資料部分。 
8.16位緊急指標:標識哪部分資料是緊急資料,因為TCP有位元組序,所以它支援優先訪問某一部分資料。 
9.40位的選項:這裡不多做解釋。

介紹完TCP協議段的格式後,我們再來看看TCP都有哪些機制來保證它的可靠性。

1.校驗和:就是最基礎的保證資料不會出錯,這裡不多做介紹。 
2.序列號:序列號保證了資料按序到達,如果有重複資料還能用來去重。這都是用可靠性的一種。 
3. 確認應答(ACK)機制:就是我們在上面介紹的序號和確認序號,我給你傳送一段資料(位元組序1-1000),你就要填充你的ACK標記位以及確認序號(確認序號填充1001),用來表示資料你已經收到了,下次要發就從位元組序為1001的資料傳送。 
4. 超時重傳機制:假設A為傳送端,B為接收端,A給B傳送一組資料,有兩種情況,A會認為資料B沒收到,第一種是A給B傳送的資料包丟了,第二種就是資料B收到了,但是B再給A傳送確認應答時,確認應答丟了,這兩種情況都是傳送端傳送資料後,如果在特定的時間內沒有收到對方的確認應答,都會認為對方沒有收到資料,進而將之前傳送的資料進行重發。這種機制就是超時重傳機制,也是TCP保證可靠性的一種。 
5.流量控制:TCP支援根據接收端的處理能力,來決定傳送資料的速度,這種機制就叫做流量控制。之前我們講過,視窗大小就是用來描述自己當前的接收能力(處理能力)的,而傳送端就是根據這個欄位來控制傳送速度。 
6.擁塞控制:由於在網路上傳輸資料的計算機有成千上萬個,可能現在網路已經非常堵塞,如果一次我們一次傳送大量資料,不僅會造成網路更加堵塞,還有可能會造成丟包的問題,當然,丟包了,可以觸發超時重傳,但是如果大量的丟包呢?所以這裡TCP就引入了慢啟動機制,也引入了一個新概念,擁塞視窗,傳送剛開始的時候,定義擁塞視窗大小為1,每收到一個ACK應答,視窗大小+1,每次傳送資料包的時候,將擁塞視窗和接收端主機反饋的視窗大小作比較,取較小值作為實際傳送的視窗(資料大小);擁塞視窗大小的增長速度是指數級別的,把這種增長機制叫做“慢啟動機”制。

看完這些TCP用來保證可靠性的機制之後,我們再來看看它最重要的一種保證可靠性的機制之一,面向連線(連線管理機制) 
正常情況下,TCP要經過3次握手建立連線,4次揮手斷開連線。 
三次握手: 
要通訊時,都是要有一方主動,正常情況下,主動的一方都為客戶端,伺服器一直處於監聽狀態,當客戶端呼叫connect,表示請求連線,此時,客戶端先會給伺服器傳送攜帶SYN同步標誌位的同步報文段,當伺服器收到之後,會發送攜帶ACK+SYN標誌位的報文,表示請求已經收到,同意建立連線,當客戶端收到後,會再向伺服器傳送ACK確認應答,connect返回,此時客戶端認為連線已經建立成功,當伺服器收到客戶端傳送的ACK後,認為連線建立成功。 
三次握手,問什麼是三次握手呢?大家肯定想過,為什麼是三次,不是四次、一次、兩次,一次握手就相當於沒握手,三次握手都已經可以解決問題了,所以不用四次,那為什麼不是兩次呢?因為兩次握手有致命的短板!因為通常情況下,客戶端都是主動建立連線的那一方,如果是兩次握手,假設最後一次報文丟了,伺服器還是會認為連線已經建立成功,要知道,維護這些連線也是需要成本的,如果有惡意軟體攻擊伺服器,只發送SYN請求連線,不接收伺服器發來的ACK+SYN,那麼伺服器就會認為每一個連線都已經建立成功了,都會維護起來,最後可能會因為開銷太大而崩潰。 
四次揮手: 
在建立連線需要有“人”主動,對方只要同意就可以,但是斷開連線就不一樣了,不僅需要一方主動,在對方同意斷開連線之後,對方也要跟“我”斷開連線,就像男女朋友分手一樣,你跟我提出分手後,我同意了,這時,你認為我已經不是你物件了,但是,我還不這樣認為,我必須也要跟你提出分手,你再同意,此時,我才認為你也不是我物件;這時,才是真的分手了。接下來我們看看詳細過程。 
在TCP斷開連線時,一方(假設為客戶端)會呼叫close(fd)關閉連線,即傳送攜帶FIN標誌位的結束報文段,表示想要斷開連線,當伺服器收到後,會發送ACK確認應答,表示我已經收到並且同意;之後,伺服器也會呼叫close(fd),即也會發送攜帶FIN標誌位的結束報文段,表示“我”也要跟你斷開連線,當客戶端收到之後,會發送ACK表示收到並且同意斷開連線,此時客戶端(主動斷開連線的一方)處於TIME_WAIT狀態,當伺服器收到後,就“真的”斷開連線,處於CLOSED狀態。TIME_WAIT(時間長度為2MSL)過後,客戶端也會“真的”斷開連線,處於CLOSED狀態。四次揮手完畢! 
TIME_WAIT:等待2倍的報文最大生存時間,為了確保最後一次報文是否被收到。

這裡寫圖片描述
TCP協議之所以應用廣泛的原因不僅僅時因為它保證了可靠性而是在這基礎之上還儘量保證效能,接下來我們就來看看TCP為了提高效能而建立的機制。 
1.滑動視窗:之前在講確認應答的時候說,“你”給“我”傳送一個數據包(序列號為1~1000),我再給你傳送一個ACK確認應答(確認序號1001)表示資料我都收到了,下次該從什麼地方發,這樣是可以保證傳輸的可靠性,但是每發一個數據包都要對應的發一個確認應答,這樣太麻煩了,而且還會影響效能,為了提高效能,就提出了一個新的概念,視窗大小,視窗大小指的是無需等待確認應答而可以繼續傳送資料的最大值(就是由接收端當前的接收緩衝區大小決定),這樣在傳送資料的時候,一次就可以傳送一個視窗大小(由很多資料包)的資料(先不考慮擁塞視窗),而不用向之前那樣,發一個,等收到確認應答之後才能發下一個,這樣傳送後,等到收到第一個包的ACK後,滑動視窗就會後移“一個”,以此類推,作業系統為了維護滑動視窗,需要開闢傳送緩衝區來記錄當前還有那些資料沒有應答,只有確認應答過的資料才能從緩衝區刪除。視窗越大,網路吞吐率就越高。 
但是如果丟包了呢? 
在傳送端開來,有兩種情況它會認為是包丟了,一種是資料包接收端收到了,但是接收端給傳送的ACK丟了,這種情況其實不影響,因為我們一次傳送多個數據包,某一個包的ACK丟了,還會收到其他後序包的ACK,這樣也能確認接收端已經收到資料;但是,還有一種情況是資料包丟了,如果是這種情況,就可能會觸發另一種保證效能的機制–快重傳機制 
2.高速重發控制(快重傳): 
這裡寫圖片描述 
3.延遲應答:延遲應答就是字面上的意思,過一會再應答,因為每次確認應答的時候我們都要在16視窗的欄位上填上自己接收緩衝區的大小,如果在收到資料包時立刻就應答的話,這樣應用層還“來不及”從接收緩衝區中拿走資料,返回的視窗大小會比較小,但是如果“過一會”再應答,這樣視窗大小可能就會大很多。因為視窗越大,網路吞吐量就越大,傳輸效率就越高。但是要注意,不是所有的資料包都可以延遲應答,“一會兒”(延遲的時間)不同作業系統不一樣。 
4.捎帶應答:因為每次如果只是為了應答就發一個數據包給對方,這樣就太浪費資源了,在實際情況當中,大多數伺服器與客戶端之間都是“一發一收”,伺服器不僅僅只是傳送資料,客戶端也不會只收收據,所以確認應答的時候,ACK就可以搭順風車,和想要傳送的資料包一起傳送給對方。