【網路程式設計】深入理解TCP的工作機制詳解
TCP的特點及其目的
為了通過IP資料報實現可靠性傳輸,需要考慮很多事情,例如資料的破壞、丟包、重複以及分片順序混亂等,TCP通過校驗和、序列號、確認應答、重發控制、連線管理以及視窗控制等機制等實現可靠性傳輸。
通過序列號與確認應答提高可靠性
在TCP中,當傳送端的資料達到接收主機事,接收機主機會返回一個已收到訊息的通知。這個訊息叫做確認應答(ACK, Positive Acknowledgement)。
TCP通過肯定的確認應答(ACK)實現可靠的資料傳輸,當傳送端將資料發出之後會等待對端的確認應答。如果有確認應答,說明資料已經成功達到對端,反之,資料丟失的可能性比較大。
如下圖所示,如果在一定時間內沒有等到確認應答,傳送端就可以認為資料已經丟失,並進行重發。由此,即使產生了丟包,仍然能保證資料能夠達到對端,實現可靠傳輸。
未收到確認應答也不一定意味著資料一定丟失,也有可能好是對方已經收到資料,只是返回的確認應答在途中丟失,這種情況也會導致傳送端沒有收到確認應答,而認為資料沒有達到目的地,從而進行重新發送。如下圖,
此外,也有可能因為一些其他原因導致確認應答延遲到達,在源主機重發資料之後才到達的情況也屢見不鮮。此時,源傳送主機只要按照機制重發資料即可。但對於目標主機而言,這簡直是一場“災難”,它會反覆收到相同的資料。而為了對上層應用提供可靠的傳輸,必須得放棄重複的資料包。為此,引入一種機制,既能識別是否已經接收資料,又能判斷是否需要接收。
上述這些確認應答處理、重發控制和重複控制等功能都可以通過序列號實現。
TCP的連線管理(三次握手)
TCP提供面向有連線的通訊傳輸。面向有連線是指在資料通訊之前先做好通訊兩端之間的準備工作。
在資料通訊通過之前,通過TCP首部發送一個SYN包作為建立連線的請求等待確認應答。TCP中傳送第一個SYN包的一方叫客戶端,接收這個包的一方叫服務端。
可以使用TCP首部用於控制的欄位來管理TCP連線。一個連線的建立與斷開,正常過程至少需要來回傳送7個包才能完成,建立一個TCP連線需要傳送3個包,因此也稱做“三次握手”。
TCP的視窗控制和重發控制
TCP以一個段為單位,每發一個段進行一次確認應答的處理,這樣包往返時間越長,通訊效能就越低。
因此引入視窗的概念,確認應答不再是以每個分段,而是以更大的單位進行確認,轉發時間將會被大幅度縮短。也就是說,傳送端主機,在傳送了一個段以後繼續傳送,而不用一直等待確認應答。
在使用視窗控制中,段丟失怎麼辦?首先,考慮確認應答未能返回的情況,在這種情況下,資料已經到達對端,無需重發。在此種情況下,某些確認應答即便丟失也無需重發。
其次,考慮某個報文丟失的情況的情況,接收主機如果收到一個自己應該接收的序號以外的資料時,會針對當前為止收到的資料返回確認應答。如下圖
擁塞控制
當計算機網路出現擁堵時,如果突然傳送一個較大量的資料,極有可能會導致整個網路的癱瘓,為了防止該問題的出現,TCP在通訊一開始就會通過一個叫慢啟動的演算法得出的數值,對傳送資料量進行控制。
首先,為了在傳送端調節所要傳送資料的量,定義了一個叫“擁塞視窗”的概念,於是在慢啟動的時候,將這個擁塞視窗的大小設定為1個數據段(1個MSS)傳送資料,之後每收到一次確認應答(ACK),擁塞視窗的值就加1。在傳送資料包時,將擁塞視窗和接收端通知的視窗大小做比較,然後取較小的值。
不過,隨著包的每次往返,擁塞視窗也會以1、2、4等指數函式增長,擁堵狀況激增甚至導致網路擁塞的發生。為了防止,引入了慢啟動閾值的概念,只要擁塞視窗的值超過閾值,每接收到一次確認應答,只允許以下面的比例放大擁塞視窗:
當TCP通訊開始後,網路吞吐量會逐漸上升,但是隨著網路擁堵的發生吞吐量也會急速下降。於是會再次進入吞吐量慢慢上升的過程。因此所謂TCP的吞吐量的特點就好象是在逐步佔領網路頻寬的感覺。
TCP首部格式
另外,TCP中沒有表示包長度和資料長度的欄位。可由IP層獲知TCP的包長可知資料的長度。
- 源埠號(Source Port):表示傳送端埠號,欄位長16位
- 目標埠號(Destination Port):表示接收端埠號,欄位長16位
- 序列號(Sequence Number):欄位長32位,序列號是指傳送資料的位置,沒傳送一次資料,就累加一次該資料的大小。
它不會從0或1開始,而是在建立連線時由計算機生成的隨機數作為其初始值,通過SYN包傳給接收端主機。然後再將每轉發過去的位元組數累加到初始值上表示資料位置,此外,在建立連線和斷開連線時傳送的SYN包和FIN包雖然都不攜帶資料,但也會作為一個位元組增加對應的序列號。 - 確認應答號(Acknowledgement Number):欄位長32位,指下一次應該收到的序列號,實際上,它是指已經收到確認應答號減一為止的資料。傳送端收到這個確認應答後可以認為在這個序號以前的資料已經被正常接收。
- 資料偏移(Data Offset):該欄位表示TCP傳輸的資料部分應該從TCP包的哪個位開始計算,當然也可以把它看做是TCP首部的長度。該欄位長4位,單位為4位元組(32位)。如上圖的TCP首部為20位元組(5*4),因此資料偏移欄位可以設定為5。反之,偏移欄位為5,則TCP從一開始到20位元組處都是TCP首部。
- 保留(Reserved):主要為了以後拓展用,4位,常設為0。
-
控制位(Control Flag):欄位長位8位,從左往右依次是:CWR、ECE、URG、ACK、PSH、RST、SYN、FIN。這些控制標誌也叫控制位。具體含義如下圖:
-
視窗大小(Window Size):欄位長16位,用於通知從相同TCP首部的確認應答號所指位置開始能接收的資料大小(8位位元組)。TCP不允許傳送超過此處所示大小的資料。不過,如果視窗為0,則表示可以傳送視窗探測,以瞭解最新的視窗大小。但這個資料必須是1個位元組。
-
校驗和(Checksum):TCP和UDP的校驗和相似,但是TCP的校驗和無法關閉。
TCP和UDP一樣在計算時使用TCP偽首部,偽首部如下圖,
在資料最後補零以令其全長為16的整數倍,首先將TCP校驗和欄位設為0,然後以16位為單位進行1的補碼和計算,再將它們總和的1的補碼和放入校驗和欄位。
接收端在接收到TCP資料後,從IP首部獲取IP地址資訊構造TCP偽首部,再進行校驗和計算。由於校驗和欄位裡儲存著除本欄位以外其他部分的和的補碼值,因此如果計算校驗和欄位在內的所有資料的16位和之後,得出的結果是“16位全部為1”說明所收到的資料是正確的。 -
緊急指標(Urgent Pointer):16位,只有在URG位為1時有效。該欄位的數值表示本報文中緊急資料的指標。正確來講,從資料部分的首位到緊急指標所指示的位置為止為緊急資料。因此也可以說緊急指標指出了緊急資料的末尾在報文段中的資料。
- 選項(Options):該欄位用於提高TCP傳輸效能,因為根據資料偏移(首部長度)進行控制,所以其最大長度為40位元組。