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ì)算機(jī)通信網(wǎng)絡(luò)的主計(jì)算機(jī)中的成對進(jìn)程之間依靠TCP提供可靠的通信服務(wù)。TCP假設(shè)它可以從較低級(jí)別的協(xié)議獲得簡單的,可能不可靠的數(shù)據(jù)報(bào)服務(wù)。 原則上,TCP應(yīng)該能夠在從硬線連接到分組交換或電路交換網(wǎng)絡(luò)的各種通信系統(tǒng)之上操作。

二、報(bào)文

1.報(bào)文格式

2.報(bào)文字段

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

3.6個(gè)重要標(biāo)識(shí)

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

三、三次握手

1.”三次握手”的詳解

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

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

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

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

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

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

四、“四次揮手”

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

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

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

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

服務(wù)器端收到從客戶端發(fā)出的TCP報(bào)文之后結(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報(bào)文中,雙方的確認(rèn)號(hào)Ack和序號(hào)Seq的值,都是在彼此Ack和Seq值的基礎(chǔ)上進(jìn)行計(jì)算的,這樣做保證了TCP報(bào)文傳輸?shù)倪B貫性,一旦出現(xiàn)某一方發(fā)出的TCP報(bào)文丟失,便無法繼續(xù)"揮手",以此確保了"四次揮手"的順利完成。

五、常見面試題

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

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

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

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

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

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

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

解決辦法:

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

 ?。?)開啟快速回收

六.常見攻擊

SYN攻擊:

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

netstat -nap | grep SYN_RECV

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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)