TCP 傳輸控制協(xié)議

2020-06-12 16:42 更新

一、簡介

傳輸控制協(xié)議(TCP,Transmission Control Protocol)是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議,由IETF的RFC 793 [1] 定義。

TCP旨在適應(yīng)支持多網(wǎng)絡(luò)應(yīng)用的分層協(xié)議層次結(jié)構(gòu)。 連接到不同但互連的計算機(jī)通信網(wǎng)絡(luò)的主計算機(jī)中的成對進(jìn)程之間依靠TCP提供可靠的通信服務(wù)。TCP假設(shè)它可以從較低級別的協(xié)議獲得簡單的,可能不可靠的數(shù)據(jù)報服務(wù)。 原則上,TCP應(yīng)該能夠在從硬線連接到分組交換或電路交換網(wǎng)絡(luò)的各種通信系統(tǒng)之上操作。

二、報文

1.報文格式

2.報文字段

字段 長度 含義
Source Port 16比特 源端口,標(biāo)識哪個應(yīng)用程序發(fā)送。
Destination Port 16比特 目的端口,標(biāo)識哪個應(yīng)用程序接收。
Sequence Number 32比特 序號字段。TCP鏈接中傳輸?shù)臄?shù)據(jù)流中每個字節(jié)都編上一個序號。序號字段的值指的是本報文段所發(fā)送的數(shù)據(jù)的第一個字節(jié)的序號。
Acknowledgment Number 32比特 確認(rèn)號,是期望收到對方的下一個報文段的數(shù)據(jù)的第1個字節(jié)的序號,即上次已成功接收到的數(shù)據(jù)字節(jié)序號加1。只有ACK標(biāo)識為1,此字段有效。
Data Offset 4比特 數(shù)據(jù)偏移,即首部長度,指出TCP報文段的數(shù)據(jù)起始處距離TCP報文段的起始處有多遠(yuǎn),以32比特(4字節(jié))為計算單位。最多有60字節(jié)的首部,若無選項字段,正常為20字節(jié)。
Reserved 6比特 保留,必須填0。
URG 1比特 緊急指針有效標(biāo)識。它告訴系統(tǒng)此報文段中有緊急數(shù)據(jù),應(yīng)盡快傳送(相當(dāng)于高優(yōu)先級的數(shù)據(jù))。
ACK 1比特 確認(rèn)序號有效標(biāo)識。只有當(dāng)ACK=1時確認(rèn)號字段才有效。當(dāng)ACK=0時,確認(rèn)號無效。
PSH 1比特 標(biāo)識接收方應(yīng)該盡快將這個報文段交給應(yīng)用層。接收到PSH = 1的TCP報文段,應(yīng)盡快的交付接收應(yīng)用進(jìn)程,而不再等待整個緩存都填滿了后再向上交付。
RST 1比特 重建連接標(biāo)識。當(dāng)RST=1時,表明TCP連接中出現(xiàn)嚴(yán)重錯誤(如由于主機(jī)崩潰或其他原因),必須釋放連接,然后再重新建立連接。
SYN 1比特 同步序號標(biāo)識,用來發(fā)起一個連接。SYN=1表示這是一個連接請求或連接接受請求。
FIN 1比特 發(fā)端完成發(fā)送任務(wù)標(biāo)識。用來釋放一個連接。FIN=1表明此報文段的發(fā)送端的數(shù)據(jù)已經(jīng)發(fā)送完畢,并要求釋放連接。
Window 16比特 窗口:TCP的流量控制,窗口起始于確認(rèn)序號字段指明的值,這個值是接收端正期望接收的字節(jié)數(shù)。窗口最大為65535字節(jié)。
Checksum 16比特 校驗字段,包括TCP首部和TCP數(shù)據(jù),是一個強(qiáng)制性的字段,一定是由發(fā)端計算和存儲,并由收端進(jìn)行驗證。在計算檢驗和時,要在TCP報文段的前面加上12字節(jié)的偽首部。
Urgent Pointer 16比特 緊急指針,只有當(dāng)URG標(biāo)志置1時緊急指針才有效。TCP的緊急方式是發(fā)送端向另一端發(fā)送緊急數(shù)據(jù)的一種方式。緊急指針指出在本報文段中緊急數(shù)據(jù)共有多少個字節(jié)(緊急數(shù)據(jù)放在本報文段數(shù)據(jù)的最前面)。
Options 可變 選項字段。TCP協(xié)議最初只規(guī)定了一種選項,即最長報文段長度(數(shù)據(jù)字段加上TCP首部),又稱為MSS。MSS告訴對方TCP“我的緩存所能接收的報文段的數(shù)據(jù)字段的最大長度是MSS個字節(jié)”。
Padding 可變 填充字段,用來補(bǔ)位,使整個首部長度是4字節(jié)的整數(shù)倍。
data 可變 TCP負(fù)載。

3.6個重要標(biāo)識

SYN(synchronous建立聯(lián)機(jī)) ACK(acknowledgement 確認(rèn)) PSH(push傳送) FIN(finish結(jié)束) RST(reset重置) URG(urgent緊急)

三、三次握手

1.”三次握手”的詳解

所謂的三次握手即TCP連接的建立。這個連接必須是一方主動打開,另一方被動打開的。以下為客戶端主動發(fā)起連接的圖解:

握手之前主動打開連接的客戶端結(jié)束CLOSED階段,被動打開的服務(wù)器端也結(jié)束CLOSED階段,并進(jìn)入LISTEN階段。隨后開始“三次握手”:

(1)首先客戶端向服務(wù)器端發(fā)送一段TCP報文,其中: 標(biāo)記位為SYN,表示“請求建立新連接”; 序號為Seq=X(X一般為1); 隨后客戶端進(jìn)入SYN-SENT階段。

(2)服務(wù)器端接收到來自客戶端的TCP報文之后,結(jié)束LISTEN階段。并返回一段TCP報文,其中: 標(biāo)志位為SYN和ACK,表示“確認(rèn)客戶端的報文Seq序號有效,服務(wù)器能正常接收客戶端發(fā)送的數(shù)據(jù),并同意創(chuàng)建新連接”(即告訴客戶端,服務(wù)器收到了你的數(shù)據(jù)); 序號為Seq=y; 確認(rèn)號為Ack=x+1,表示收到客戶端的序號Seq并將其值加1作為自己確認(rèn)號Ack的值;隨后服務(wù)器端進(jìn)入SYN-RCVD階段。

(3)客戶端接收到來自服務(wù)器端的確認(rèn)收到數(shù)據(jù)的TCP報文之后,明確了從客戶端到服務(wù)器的數(shù)據(jù)傳輸是正常的,結(jié)束SYN-SENT階段。并返回最后一段TCP報文。其中: 標(biāo)志位為ACK,表示“確認(rèn)收到服務(wù)器端同意連接的信號”(即告訴服務(wù)器,我知道你收到我發(fā)的數(shù)據(jù)了); 序號為Seq=x+1,表示收到服務(wù)器端的確認(rèn)號Ack,并將其值作為自己的序號值; 確認(rèn)號為Ack=y+1,表示收到服務(wù)器端序號Seq,并將其值加1作為自己的確認(rèn)號Ack的值; 隨后客戶端進(jìn)入ESTABLISHED階段。 服務(wù)器收到來自客戶端的“確認(rèn)收到服務(wù)器數(shù)據(jù)”的TCP報文之后,明確了從服務(wù)器到客戶端的數(shù)據(jù)傳輸是正常的。結(jié)束SYN-SENT階段,進(jìn)入ESTABLISHED階段。 在客戶端與服務(wù)器端傳輸?shù)腡CP報文中,雙方的確認(rèn)號Ack和序號Seq的值,都是在彼此Ack和Seq值的基礎(chǔ)上進(jìn)行計算的,這樣做保證了TCP報文傳輸?shù)倪B貫性。一旦出現(xiàn)某一方發(fā)出的TCP報文丟失,便無法繼續(xù)"握手",以此確保了"三次握手"的順利完成。 此后客戶端和服務(wù)器端進(jìn)行正常的數(shù)據(jù)傳輸。這就是“三次握手”的過程。

2.“三次握手”的動態(tài)過程

四、“四次揮手”

所謂的四次揮手即TCP連接的釋放(解除)。連接的釋放必須是一方主動釋放,另一方被動釋放。以下為客戶端主動發(fā)起釋放連接的圖解:

揮手之前主動釋放連接的客戶端結(jié)束ESTABLISHED階段。隨后開始“四次揮手”: (1)首先客戶端想要釋放連接,向服務(wù)器端發(fā)送一段TCP報文,其中: 標(biāo)記位為FIN,表示“請求釋放連接“; 序號為Seq=U; 隨后客戶端進(jìn)入FIN-WAIT-1階段,即半關(guān)閉階段。并且停止在客戶端到服務(wù)器端方向上發(fā)送數(shù)據(jù),但是客戶端仍然能接收從服務(wù)器端傳輸過來的數(shù)據(jù)。 注意:這里不發(fā)送的是正常連接時傳輸?shù)臄?shù)據(jù)(非確認(rèn)報文),而不是一切數(shù)據(jù),所以客戶端仍然能發(fā)送ACK確認(rèn)報文。

(2)服務(wù)器端接收到從客戶端發(fā)出的TCP報文之后,確認(rèn)了客戶端想要釋放連接,隨后服務(wù)器端結(jié)束ESTABLISHED階段,進(jìn)入CLOSE-WAIT階段(半關(guān)閉狀態(tài))并返回一段TCP報文,其中: 標(biāo)記位為ACK,表示“接收到客戶端發(fā)送的釋放連接的請求”; 序號為Seq=V; 確認(rèn)號為Ack=U+1,表示是在收到客戶端報文的基礎(chǔ)上,將其序號Seq值加1作為本段報文確認(rèn)號Ack的值; 隨后服務(wù)器端開始準(zhǔn)備釋放服務(wù)器端到客戶端方向上的連接。 客戶端收到從服務(wù)器端發(fā)出的TCP報文之后,確認(rèn)了服務(wù)器收到了客戶端發(fā)出的釋放連接請求,隨后客戶端結(jié)束FIN-WAIT-1階段,進(jìn)入FIN-WAIT-2階段 前"兩次揮手"既讓服務(wù)器端知道了客戶端想要釋放連接,也讓客戶端知道了服務(wù)器端了解了自己想要釋放連接的請求。于是,可以確認(rèn)關(guān)閉客戶端到服務(wù)器端方向上的連接了。

(3)服務(wù)器端自從發(fā)出ACK確認(rèn)報文之后,經(jīng)過CLOSED-WAIT階段,做好了釋放服務(wù)器端到客戶端方向上的連接準(zhǔn)備,再次向客戶端發(fā)出一段TCP報文,其中: 標(biāo)記位為FIN,ACK,表示“已經(jīng)準(zhǔn)備好釋放連接了”。注意:這里的ACK并不是確認(rèn)收到服務(wù)器端報文的確認(rèn)報文。 序號為Seq=W; 確認(rèn)號為Ack=U+1;表示是在收到客戶端報文的基礎(chǔ)上,將其序號Seq值加1作為本段報文確認(rèn)號Ack的值。 隨后服務(wù)器端結(jié)束CLOSE-WAIT階段,進(jìn)入LAST-ACK階段。并且停止在服務(wù)器端到客戶端的方向上發(fā)送數(shù)據(jù),但是服務(wù)器端仍然能夠接收從客戶端傳輸過來的數(shù)據(jù)。

(4)客戶端收到從服務(wù)器端發(fā)出的TCP報文,確認(rèn)了服務(wù)器端已做好釋放連接的準(zhǔn)備,結(jié)束FIN-WAIT-2階段,進(jìn)入TIME-WAIT階段,并向服務(wù)器端發(fā)送一段報文,其中: 標(biāo)記位為ACK,表示“接收到服務(wù)器準(zhǔn)備好釋放連接的信號”。 序號為Seq=U+1;表示是在收到了服務(wù)器端報文的基礎(chǔ)上,將其確認(rèn)號Ack值作為本段報文序號的值。 確認(rèn)號為Ack=W+1;表示是在收到了服務(wù)器端報文的基礎(chǔ)上,將其序號Seq值作為本段報文確認(rèn)號的值。 隨后客戶端開始在TIME-WAIT階段等待2MSL 為什么要客戶端要等待2MSL呢?見后文。

服務(wù)器端收到從客戶端發(fā)出的TCP報文之后結(jié)束LAST-ACK階段,進(jìn)入CLOSED階段。由此正式確認(rèn)關(guān)閉服務(wù)器端到客戶端方向上的連接。 客戶端等待完2MSL之后,結(jié)束TIME-WAIT階段,進(jìn)入CLOSED階段,由此完成“四次揮手”。

后“兩次揮手”既讓客戶端知道了服務(wù)器端準(zhǔn)備好釋放連接了,也讓服務(wù)器端知道了客戶端了解了自己準(zhǔn)備好釋放連接了。于是,可以確認(rèn)關(guān)閉服務(wù)器端到客戶端方向上的連接了,由此完成“四次揮手”。 與“三次揮手”一樣,在客戶端與服務(wù)器端傳輸?shù)腡CP報文中,雙方的確認(rèn)號Ack和序號Seq的值,都是在彼此Ack和Seq值的基礎(chǔ)上進(jìn)行計算的,這樣做保證了TCP報文傳輸?shù)倪B貫性,一旦出現(xiàn)某一方發(fā)出的TCP報文丟失,便無法繼續(xù)"揮手",以此確保了"四次揮手"的順利完成。

五、常見面試題

1.為什么建立連接協(xié)議是三次握手,而關(guān)閉連接卻是四次握手呢?

這是因為服務(wù)端的LISTEN狀態(tài)下的SOCKET當(dāng)收到SYN報文的建連請求后,它可以把ACK和SYN(ACK起應(yīng)答作用,而SYN起同步作用)放在 一個報文里來發(fā)送。

但關(guān)閉連接時,當(dāng)收到對方的FIN報文通知時,它僅僅表示對方?jīng)]有數(shù)據(jù)發(fā)送給你了;但未必你所有的數(shù)據(jù)都全部發(fā)送給對方了,所以你可以 未必會馬上會關(guān)閉SOCKET,也即你可能還需要發(fā)送一些數(shù)據(jù)給對方之后,再發(fā)送FIN報文給對方來表示你同意現(xiàn)在可以關(guān)閉連接了,所以它這里的ACK報 文和FIN報文多數(shù)情況下都是分開發(fā)送的.

2.為什么TIME_WAIT狀態(tài)還需要等2MSL后才能返回到CLOSED狀態(tài)?

因為雖然雙方都同意關(guān)閉連接了,而且握手的4個報文也都協(xié)調(diào)和發(fā)送完畢,按理可以直接回到CLOSED狀態(tài)(就好比從SYN_SEND狀態(tài)到ESTABLISH狀態(tài)那樣);但是我們認(rèn)為網(wǎng)絡(luò)是不可靠的,你無法保證你最后發(fā)送的ACK報文會一定被對方收到,因此對方處于LAST_ACK狀態(tài)下的SOCKET可能會因為超時未收到ACK報文,而重發(fā)FIN報文,所以這個TIME_WAIT狀態(tài)的作用就是用來重發(fā)可能丟失的ACK報文。

3.大量TIME_WAIT產(chǎn)生的原因及解決辦法

   原因:對于基于TCP的HTTP協(xié)議,關(guān)閉TCP連接的是Server端,這樣,Server端回進(jìn)入TIME_WAIT狀態(tài),可想而知,對于訪問量大的Web Server,會存在大量的TIME_WAIT狀態(tài)。

解決辦法:

  (1)開啟socket重用,允許TIME_WAIT的socket重新用于TCP連接

  (2)開啟快速回收

六.常見攻擊

SYN攻擊:

在三次握手過程中,Server發(fā)送SYN-ACK之后,收到Client的ACK之前的TCP連接稱為半連接(half-open connect),此時Server處于SYN_RCVD狀態(tài),當(dāng)收到ACK后,Server轉(zhuǎn)入ESTABLISHED狀態(tài)。SYN攻擊就是Client在短時間內(nèi)偽造大量不存在的IP地址,并向Server不斷地發(fā)送SYN包,Server回復(fù)確認(rèn)包,并等待Client的確認(rèn),由于源地址是不存在的,因此,Server需要不斷重發(fā)直至超時,這些偽造的SYN包將產(chǎn)時間占用未連接隊列,導(dǎo)致正常的SYN請求因為隊列滿而被丟棄,從而引起網(wǎng)絡(luò)堵塞甚至系統(tǒng)癱瘓。SYN攻擊時一種典型的DDOS攻擊,檢測SYN攻擊的方式非常簡單,即當(dāng)Server上有大量半連接狀態(tài)且源IP地址是隨機(jī)的,則可以斷定遭到SYN攻擊了,使用如下命令可以讓之現(xiàn)行:

netstat -nap | grep SYN_RECV

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號