TCP/IP 三次握手與四次揮手

三次握手的過程:

第一次握手

客戶端向服務(wù)器端發(fā)送請求報文:SYN=1,ACK=0,seq=x,發(fā)送完畢后,客戶端進(jìn)入SYN-SENT狀態(tài);

  1. SYN=1,ACK=0表示為連接請求報文;
  2. x為客戶端字節(jié)流的初始序列號;
  3. SYN=1的報文不能帶有數(shù)據(jù)部分,但需要消耗一個序列號。
第二次握手

服務(wù)器端收到客戶端的連接請求報文,服務(wù)器端向客戶端發(fā)送應(yīng)答:SYN=1,ACK=1,seq=y,ack=x+1,發(fā)送完服務(wù)器進(jìn)入SYN-REVD狀態(tài);

  1. SYN=1,ACK=1表示該報文為同意連接的報文;
  2. seq=y表示發(fā)送者發(fā)送字節(jié)流的初始序列號;
  3. ack=x+1表示希望對方下一個數(shù)據(jù)包發(fā)送從序號x+1開始的字節(jié)流。
第三次握手

客戶端在收到同意連接的報文之后,還要向服務(wù)器端發(fā)送一個確認(rèn)報文,表示我已近收到了服務(wù)器同意連接的報文:SYN=0,ACK=1,seq=x+1,ack=y+1,發(fā)送完客戶端進(jìn)入ESTABLISHED狀態(tài)。
第三次握手已經(jīng)可以攜帶數(shù)據(jù)

TCP 3次握手示意圖
同時打開(simultaneous open)

服務(wù)器端和客戶端同時對雙發(fā)的端口發(fā)起連接,幾乎同時發(fā)起SYN報文進(jìn)入SYN-SENT,雙方在收到SYN報文,回復(fù)ACK報文進(jìn)入SYN_REVD,雙方在收到ACK報文后進(jìn)入ESTABLISHED。

四次揮手

客戶端和服務(wù)器端需要發(fā)4個包以確定連接的斷開,客戶端和服務(wù)器端均可發(fā)起,一個方向連接的斷開需要2次,因此總共需要4次

第一次揮手

客戶認(rèn)為數(shù)據(jù)已經(jīng)傳送完畢,需要釋放連接,因此向服務(wù)器發(fā)送連接釋放請求:FIN=1,seq=u,發(fā)送完畢后進(jìn)入FIN-WAIT-1.

  1. FIN=1表示該報文是一個連接釋放報文;
  2. seq=u-1是數(shù)據(jù)最后一個字節(jié)的序號。
第二次揮手

服務(wù)器收到客戶端發(fā)送的釋放報文,會通知響應(yīng)的程序表示客戶端已無數(shù)據(jù)發(fā)送,需要關(guān)閉客戶端->服務(wù)器的連接,并想客戶端發(fā)送連接釋放的應(yīng)答:ACK=1,ack=u+1,seq=v,發(fā)送完畢后進(jìn)入CLOSE-WAIT狀態(tài),此時,服務(wù)器仍可以往客戶端發(fā)送數(shù)據(jù)。

  1. ACK=1,表示這是一個應(yīng)答報文;
  2. ack=u+1,表示前u字節(jié)的數(shù)據(jù)已經(jīng)收到;
  3. seq=v,表示服務(wù)器端該次發(fā)送數(shù)據(jù)的起始字節(jié)為v。
    客戶端收到連接釋放確認(rèn)報文后,進(jìn)入FIN-WAIT2狀態(tài),等待服務(wù)器的連接釋放請求。
第三次揮手

服務(wù)器發(fā)發(fā)完數(shù)據(jù)并打算斷開請求,向客戶端發(fā)送連接釋放請求:FIN=1, ack=u+1,seq=w,發(fā)送完畢后,服務(wù)器進(jìn)入LAST-ACK狀態(tài)。

第四次揮手

客戶端收到服務(wù)器端的連接釋放請求后,向服務(wù)器發(fā)送應(yīng)答:ACK=1,seq=u+1,seq=w+1,發(fā)送完畢后,客戶端進(jìn)入TIME-WAIT,并等待2MSL時間,若此時間段內(nèi)沒有再次收到服務(wù)器端的重發(fā)請求的話,進(jìn)入CLOSED狀態(tài)。
服務(wù)器在收到客戶端發(fā)送的應(yīng)答報文,直接進(jìn)入CLOSED狀態(tài)。

TCP 4次揮手示意圖
TCP 狀態(tài)轉(zhuǎn)發(fā)圖

由上圖看到,TIME-WAIT有3中情況會進(jìn)入:
①上面講述的由FIN-WAIT-2進(jìn)入;
②由CLOSING狀態(tài)進(jìn)入:客戶端再發(fā)送FIN報文后等待服務(wù)器的ACK應(yīng)答報文,此時服務(wù)器也正好發(fā)起了FIN報文,客戶端再收到ACK之前先收到了該FIN報文,客戶端再回復(fù)ACK報文后進(jìn)入CLOSING狀態(tài),繼續(xù)等待服務(wù)器的ACK報文;(這種情況又稱為同時斷開(simultaneous close))
③由TIME_WAIT_1直接進(jìn)入:服務(wù)器端在收到客戶端的FIN報文時,同時發(fā)送FIN+ACK給客戶端,客戶端再收到這個FIN+ACK后回復(fù)ACK報文,然后直接進(jìn)入TIME-WAIT狀態(tài)。

為什么需要三次握手

在不可靠信道上可靠地傳輸信息
①A向B發(fā)起通信,如果B再收到SYN信號之后向A發(fā)起SYN+ACK包,如果A不向B響應(yīng)ACK包,B無法確認(rèn)A是否收到自己的SYN序列號,也就無法和A就己方的SYN序列號達(dá)成一致,因此三次握手其實(shí)可以理解成為2次單向通訊。
②為了避免網(wǎng)絡(luò)中失效的請求連接,還是A->B,如果第一次請求報文在某個節(jié)點(diǎn)滯留了很久才到B,此時A和B已經(jīng)完成了通訊。B會誤以為A又發(fā)起了一次連接,會回復(fù)SYN+ACK,如果沒有第三次握手,B在發(fā)送完SYN+ACK之后會進(jìn)入Establish狀態(tài),一直等待A端數(shù)據(jù);有了第三次握手,A在說到無效的SYN+ACK會丟棄,B由于沒有收到最后一個ACK報文,在一段時間內(nèi)就會認(rèn)為A無意建立連接,故放棄該連接。

為什么要經(jīng)過2MSL才進(jìn)入CLOSED狀態(tài)

MSL(Maximum Segment Lifetime),即報文最大生存時間,他是任何報文在網(wǎng)絡(luò)上存在的最長時間,超過這個時間報文將被丟棄。RFC 793中規(guī)定MSL為2分鐘,實(shí)際應(yīng)用中常用的是30秒,1分鐘和2分鐘等。(IP報文頭有一個TTL(Time To Live),這個值由源端設(shè)定但不是指定具體時間,每經(jīng)過一個節(jié)點(diǎn)值減1,當(dāng)值為0,該報文會被丟棄被節(jié)點(diǎn)丟棄,并發(fā)送一個ICMP報文給源端。 TTL與MSL是有關(guān)系的但不是簡單的相等的關(guān)系,MSL一定要大于等于TTL)
原因有2:①保證TCP連接能夠有效關(guān)閉;②保證這次連接的重復(fù)報文在網(wǎng)絡(luò)中消失。
如果A發(fā)完應(yīng)答請求后直接進(jìn)入CLOSED狀態(tài),該應(yīng)答丟失,B等待超時就會進(jìn)行重發(fā),此時A已經(jīng)關(guān)閉,會發(fā)送RST報文,B收到RST回通知上層,雖然數(shù)據(jù)沒有丟失,但連接卻不是正常關(guān)閉,這叫異常關(guān)閉。
如果A直接CLOSED,此時B又發(fā)起了一個新連接,無法保證兩方的端口不是和上次一樣,如果連接在相同的端口上建立,此時延時的某些數(shù)據(jù)在新連接建立之后達(dá)到目的端,此時新數(shù)據(jù)和舊數(shù)據(jù)可能會混淆,造成錯誤,因此讓其等待在2MSL后才進(jìn)入CLOSED,可以保證本次連接的所有數(shù)據(jù)都已經(jīng)到達(dá)目的端。(實(shí)際應(yīng)用中,可以設(shè)置socket的SO_REUSEADDR選項(xiàng),使端口無需等待2MSL即可使用,SO_REUSEADDR用于對TCP套接字處于TIME_WAIT狀態(tài)下的socket,才可以重復(fù)綁定使用。)

為什么連接是3次握手,而斷開是四次揮手

因?yàn)檫B接的時候,可以將SYN和ACK放在同一個報文發(fā)送;而FIN報文僅僅表示對方已經(jīng)發(fā)送完所有數(shù)據(jù),我方未必發(fā)送完,因此讓我方可以后面再發(fā)送FIN報文來表示關(guān)閉連接。

SYN攻擊

通常,服務(wù)器會維護(hù)一個半連接隊(duì)列,每一個服務(wù)器端收到客戶端的SYN包,在回復(fù)SYN+ACK之后都會放進(jìn)這個隊(duì)列,該隊(duì)列的每一項(xiàng)都在等待服務(wù)器的ACK包,都處于SYN-REVD狀態(tài),當(dāng)服務(wù)器收到客戶端的ACK包只有,都會從隊(duì)列中將該連接刪除。
SYN攻擊就是利用了TCP/IP的這一個特性,客戶端偽造大量不存在的IP,想服務(wù)器端發(fā)送大量的SYN連接請求包,服務(wù)器回復(fù)SYN+ACK回應(yīng)包,并等待客戶端的確認(rèn),由于原地址不存在,服務(wù)器會一直重發(fā)并超時,這些偽造的連接請求會長時間占滿半連接隊(duì)列,正常的SYN請求會被丟棄,從而引起服務(wù)不可用。

TCP Fast Open(TFO)了解一下

它通過握手開始時的SYN包中的TFO cookie來驗(yàn)證一個之前連接過的客戶端。如果驗(yàn)證成功,它可以在三次握手最終的ACK包收到之前就開始發(fā)送數(shù)據(jù),這樣便跳過了一個繞路的行為,更在傳輸開始時就降低了延遲。這個加密的Cookie被存儲在客戶端,在一開始的連接時被設(shè)定好。然后每當(dāng)客戶端連接時,這個Cookie被重復(fù)返回。(參考:維基百科)
Linux3.7開始支持打開TFO

Reference

  1. 讀懂TCP狀態(tài)轉(zhuǎn)移
  2. Wiki-TCP快速打開

關(guān)于作者

限于本人的水平,可能某些地方表達(dá)的不太準(zhǔn)確,敬請指教。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容