經(jīng)典面試題:TCP 三次握手、四次揮手詳解
在網(wǎng)絡(luò)通信的復(fù)雜架構(gòu)里,“三次握手”與“四次揮手”仿若一座無(wú)形的橋梁,它們是連接客戶端與服務(wù)器的關(guān)鍵紐帶。這座“橋梁”不僅確保了連接的穩(wěn)固建立,還保障了連接的有序結(jié)束,使得網(wǎng)絡(luò)世界中的信息能夠順暢、準(zhǔn)確地流動(dòng)。
在面試過程中,TCP 三次握手、四次揮手也經(jīng)常被問到的問題。本文就來(lái)快速、詳細(xì)的介紹下 TCP 三次握手、四次揮手的全部過程。
TCP 的三次握手和四次揮手實(shí)質(zhì)就是 TCP 通信的連接和斷開:
- 三次握手:同步雙方的初始序列號(hào)(ISN),確認(rèn)雙方收發(fā)能力正常;
- 四次揮手:雙方獨(dú)立關(guān)閉數(shù)據(jù)通道,確保數(shù)據(jù)完整傳輸。
一、TCP頭格式組成
為了使你更好的理解 TCP 三次握手和四次揮手過程,本小節(jié)先介紹下 TCP 頭部格式。
(1) 源端口號(hào)和目的端口號(hào):代表連接發(fā)起方和連接接收方
(2) 序號(hào):在建立連接時(shí),由計(jì)算機(jī)生產(chǎn)的隨機(jī)數(shù)作為初始值,通過SYN包傳給接收端主機(jī),每發(fā)送一次數(shù)據(jù),就累加一次該數(shù)據(jù)字節(jié)數(shù)的大小。用來(lái)解決網(wǎng)絡(luò)包亂序問題。
(3) 確認(rèn)序號(hào):指下一次期望收到的數(shù)據(jù)的序號(hào),發(fā)送端收到這個(gè)確認(rèn)應(yīng)答以后,可以認(rèn)為在這個(gè)序號(hào)以前的數(shù)據(jù),都已經(jīng)被正常接收。 用來(lái)解決網(wǎng)絡(luò)丟包的問題
(4) 標(biāo)志位,如上圖,一共6個(gè)
- URG
- ACK:該位為 1 時(shí),「確認(rèn)應(yīng)答」的字段變?yōu)橛行?,TCP 規(guī)定除了最初建立連接時(shí)的 SYN 包之外該位必須設(shè)置為 1
- PSH
- RST:該位為 1 時(shí),表示 TCP 連接中出現(xiàn)異常必須強(qiáng)制斷開連接。
- SYN:該位為 1 時(shí),表示希望建立連接,并在其「序列號(hào)」的字段進(jìn)行序列號(hào)初始值的設(shè)定。
- FIN:該位為 1 時(shí),表示今后不會(huì)再有數(shù)據(jù)發(fā)送,希望斷開連接。當(dāng)通信結(jié)束希望斷開連接時(shí),通信雙方的主機(jī)之間就可以相互交換 FIN 位為 1 的 TCP 段。
(5) 數(shù)據(jù):連接需要發(fā)送的內(nèi)容。
二、建立連接:三次握手
三次握手(Three-way Handshake)是 TCP 協(xié)議中用于建立連接的一個(gè)重要環(huán)節(jié)。在這一過程中,客戶端和服務(wù)器需要互相發(fā)送三個(gè)數(shù)據(jù)包,以確保雙方的接收和發(fā)送能力均正常,并為后續(xù)的數(shù)據(jù)傳輸指定初始化序列號(hào),從而確保數(shù)據(jù)傳輸?shù)目煽啃浴?/p>
TCP 三次握手流程圖如下所示:
圖中字符詳解:
- SYN:代表連接請(qǐng)求或接收的報(bào)文段。
- seq:指發(fā)送的第一個(gè)字節(jié)的序號(hào)。
- ACK:確認(rèn)報(bào)文段,用于回應(yīng) SYN。
- ack:確認(rèn)號(hào),表示希望收到的下一個(gè)數(shù)據(jù)的第一個(gè)字節(jié)的序號(hào)。
在 TCP 協(xié)議中,主動(dòng)發(fā)起連接請(qǐng)求的一方被稱為客戶端,而被動(dòng)等待連接的一方則被稱為服務(wù)端。無(wú)論是客戶端還是服務(wù)端,一旦 TCP 連接成功建立,雙方均可進(jìn)行數(shù)據(jù)的發(fā)送與接收。
連接建立之初,服務(wù)器和客戶端都處于 CLOSED 狀態(tài)。在通信正式開始前,雙方需要分別創(chuàng)建自己的傳輸控制塊(TCB)。服務(wù)器完成 TCB 創(chuàng)建后,會(huì)進(jìn)入 LISTEN 狀態(tài),隨時(shí)準(zhǔn)備接收客戶端發(fā)來(lái)的連接請(qǐng)求。
1. 第一次握手
客戶端向服務(wù)端發(fā)送一個(gè) SYN 報(bào)文(SYN=1),并指明客戶端的初始化序列號(hào) ISN(x),即圖中的 seq=x,它表示本報(bào)文段所發(fā)送的數(shù)據(jù)的第一個(gè)字節(jié)的序號(hào)。在發(fā)送 SYN 報(bào)文后,客戶端進(jìn)入 SYN_SENT 狀態(tài),意味著它正在等待服務(wù)端的連接確認(rèn)。
SYN_SENT 狀態(tài)解釋:當(dāng)客戶端發(fā)送連接請(qǐng)求后,它進(jìn)入 SYN_SENT 狀態(tài),等待服務(wù)端的響應(yīng)。在這個(gè)狀態(tài)下,客戶端準(zhǔn)備好了接受服務(wù)端的連接確認(rèn)。
TCP 協(xié)議規(guī)定:SYN=1 的報(bào)文段是用于建立連接的請(qǐng)求,它不攜帶任何數(shù)據(jù),但會(huì)消耗一個(gè)序號(hào)。這是 TCP 協(xié)議確保連接建立過程中的有序性和可靠性的一種方式。
2. 第二次握手
服務(wù)器在接收到客戶端的 SYN 報(bào)文后,會(huì)以 SYN 報(bào)文作為回應(yīng)(SYN=1),并賦予自己獨(dú)特的初始化序列號(hào)ISN(y),即圖中的 seq=y。同時(shí),服務(wù)器將客戶端的 ISN+1 設(shè)置為確認(rèn)號(hào) ack 的值,以此確認(rèn)已收到客戶端的 SYN 報(bào)文,并期待接收到的下一個(gè)數(shù)據(jù)報(bào)的起始序號(hào)為 x+1。在此之后,服務(wù)器會(huì)進(jìn)入 SYN-RCVD 狀態(tài),等待對(duì)連接請(qǐng)求的進(jìn)一步確認(rèn)。
SYN-RCVD 狀態(tài)解析:當(dāng)服務(wù)器在收到并發(fā)送連接請(qǐng)求后,會(huì)進(jìn)入 SYN-RCVD 狀態(tài),此時(shí)它正在等待對(duì)初始連接請(qǐng)求的確認(rèn)。在這個(gè)狀態(tài)下,服務(wù)器已經(jīng)準(zhǔn)備好接受來(lái)自客戶端的進(jìn)一步通信。
TCP 協(xié)議規(guī)定:SYN=1 且 ACK=1 的報(bào)文段是用于確認(rèn)連接的應(yīng)答,它同樣不攜帶任何數(shù)據(jù),但通過確認(rèn)號(hào)的使用,確保了連接建立過程中的有序性和可靠性。
3. 第三次握手
在收到服務(wù)器發(fā)送的 SYN 報(bào)文后,客戶端會(huì)回應(yīng)一個(gè) ACK 報(bào)文。這個(gè) ACK 報(bào)文將服務(wù)器的 ISN+1 作為 ack 的值,表明客戶端已經(jīng)收到了服務(wù)器的 SYN 報(bào)文,并期待接收到的下一個(gè)數(shù)據(jù)報(bào)的起始序號(hào)為 y+1。
同時(shí),客戶端將自己的序列號(hào) seq 設(shè)置為 x+1,即初始序列號(hào) seq=x 增加 1。完成這些操作后,客戶端進(jìn)入 ESTABLISHED 狀態(tài),表示連接已成功建立。服務(wù)器在收到這個(gè) ACK 報(bào)文后,也會(huì)轉(zhuǎn)入 ESTABLISHED 狀態(tài),此時(shí)雙方連接的建立工作全部完成。
ESTABLISHED 狀態(tài)解釋:當(dāng)一個(gè) TCP 連接進(jìn)入 ESTABLISHED 狀態(tài)時(shí),它意味著連接已經(jīng)打開,數(shù)據(jù)可以開始在雙方之間傳送。
三、斷開連接:四次揮手
TCP 連接的終止需要經(jīng)過四次包的交換,因此被稱為四次揮手。在這四次交換中,客戶端或服務(wù)器都可以主動(dòng)發(fā)起連接的釋放動(dòng)作。值得注意的是,TCP 連接是雙向的,因此四次揮手中,前兩次主要用于斷開一個(gè)方向的連接,后兩次則用于斷開另一方向的連接。
1. 第一次揮手
客戶端首先發(fā)送一個(gè) FIN 報(bào)文,其中包含一個(gè)序列號(hào) seq=u,表示請(qǐng)求連接終止。在發(fā)送完畢后,客戶端停止數(shù)據(jù)發(fā)送,并主動(dòng)關(guān)閉 TCP 連接。此時(shí),客戶端進(jìn)入 FIN_WAIT_1 狀態(tài),等待服務(wù)器的確認(rèn)。
FIN_WAIT_1 狀態(tài)解析:該狀態(tài)表示客戶端正在等待遠(yuǎn)程 TCP 的連接中斷請(qǐng)求,或者等待先前連接中斷請(qǐng)求的確認(rèn)。FIN=1 標(biāo)志著該報(bào)文段是一個(gè)連接釋放請(qǐng)求。而 seq=u 則代表客戶端向服務(wù)器發(fā)送的最后一個(gè)字節(jié)的序號(hào)。
2. 第二次揮手
服務(wù)端在收到客戶端的 FIN 報(bào)文后,會(huì)發(fā)送一個(gè) ACK 報(bào)文作為回應(yīng)。這個(gè) ACK 報(bào)文中,序列號(hào)值設(shè)為客戶端序號(hào)值加 1,意在確認(rèn)已收到客戶端的報(bào)文。隨后,服務(wù)端進(jìn)入 CLOSE_WAIT 狀態(tài),等待本地用戶的連接中斷請(qǐng)求。
CLOSE_WAIT 狀態(tài)解析:在此狀態(tài)下,服務(wù)端等待來(lái)自本地用戶的連接釋放請(qǐng)求。ACK 報(bào)文中的 ACK=1 表示應(yīng)答,而 seq=v 則指明了服務(wù)端釋放應(yīng)答報(bào)文段的首字節(jié)序號(hào)。同時(shí),ack=u+1 表明服務(wù)端希望從第 u+1 個(gè)字節(jié)開始接收?qǐng)?bào)文段,并已成功接收了前 u 個(gè)字節(jié)。
完成第二次揮手后,客戶端到服務(wù)端的連接已釋放,服務(wù)端不再接收客戶端數(shù)據(jù),而客戶端也已無(wú)數(shù)據(jù)待發(fā)送。然而,服務(wù)端到客戶端的連接仍保持開啟,若服務(wù)端在此期間發(fā)送數(shù)據(jù),客戶端仍需正常接收。此狀態(tài)將持續(xù)一段時(shí)間,直至整個(gè) CLOSE-WAIT 狀態(tài)結(jié)束。
3. 第三次揮手
服務(wù)端在完成數(shù)據(jù)的發(fā)送后,會(huì)向客戶端發(fā)送一個(gè)連接釋放報(bào)文。這個(gè)報(bào)文頭包含 FIN 標(biāo)志位為 1,以及 ack 序號(hào)值為 u+1。由于在 CLOSE_WAIT 狀態(tài)期間,服務(wù)端可能又發(fā)送了一些數(shù)據(jù),假設(shè)此時(shí)的序列號(hào)為 seq=w。發(fā)送完畢后,服務(wù)端進(jìn)入 LAST_ACK 狀態(tài),等待來(lái)自客戶端的連接中斷確認(rèn)。
4. 第四次揮手
客戶端在收到服務(wù)端的 FIN 報(bào)文后,會(huì)響應(yīng)一個(gè) ACK 報(bào)文,其中 ack 序號(hào)值為 w+1,同時(shí)將自己的序列值加 1作為 ACK 報(bào)文的 seq 序號(hào)值,即 seq=u+1。此后,客戶端進(jìn)入 TIME_WAIT 狀態(tài)。
TIME_WAIT:確保遠(yuǎn)程 TCP 收到連接中斷請(qǐng)求的確認(rèn)狀態(tài)會(huì)持續(xù) 2MSL(最長(zhǎng)報(bào)文段壽命)的時(shí)間。在此期間, TCP 連接并未完全釋放。若在這段時(shí)間內(nèi)未收到服務(wù)端的重發(fā)請(qǐng)求,客戶端將進(jìn)入 CLOSED 狀態(tài),并撤銷 TCB。
服務(wù)端在收到客戶端的確認(rèn) ACK 報(bào)文后,會(huì)立即進(jìn)入 CLOSED 狀態(tài),并撤銷 TCB,從而結(jié)束此次 TCP 連接。值得注意的是,服務(wù)端結(jié)束 TCP 連接的時(shí)間點(diǎn)通常早于客戶端。
四、四次揮手 vs 三次握手
階段 | 三次握手 | 四次揮手 |
目的 | 建立連接,同步序列號(hào) | 安全關(guān)閉雙向數(shù)據(jù)通道 |
交互次數(shù) | 3次 | 4次 |
關(guān)鍵標(biāo)志位 | SYN 、ACK | FIN 、ACK |
狀態(tài)復(fù)雜度 | 簡(jiǎn)單(直接建立) | 復(fù)雜(需處理半關(guān)閉和TIME_WAIT) |
五、關(guān)聯(lián)面試題
1. 為何 TCP 建立連接時(shí)采用三次握手而非兩次或四次?
- 兩次不夠:無(wú)法確認(rèn)客戶端的接收能力(若服務(wù)端的SYN-ACK丟失,客戶端不知服務(wù)端已就緒)。
- 四次冗余:三次已能確保雙向通信能力,無(wú)需額外交互。
具體原因如下:
- 確保雙方都能發(fā)送和接收:三次握手可以確保雙方都具備發(fā)送和接收數(shù)據(jù)的能力。在第一次握手時(shí),客戶端發(fā)起請(qǐng)求,第二次握手時(shí),服務(wù)器確認(rèn)收到了請(qǐng)求并表示自己也可以通信,第三次握手時(shí),客戶端確認(rèn)收到了服務(wù)器的響應(yīng)。這保證了通信的可靠性。
- 防止重復(fù)連接初始化問題:假設(shè)沒有三次握手,而是兩次握手,那么可能會(huì)出現(xiàn)一種情況:客戶端發(fā)送了一個(gè)連接請(qǐng)求(SYN),但由于網(wǎng)絡(luò)問題,服務(wù)器沒有及時(shí)收到或者延遲了。客戶端在等待了一段時(shí)間后認(rèn)為請(qǐng)求失敗,重新發(fā)送了一個(gè)新的 SYN,而此時(shí)第一個(gè) SYN 報(bào)文延遲到達(dá)服務(wù)器,服務(wù)器誤認(rèn)為客戶端又發(fā)起了一次新的連接請(qǐng)求,從而產(chǎn)生混亂。通過三次握手,能夠有效避免這種問題,確保連接的一致性。
- 同步初始序列號(hào):三次握手過程中,客戶端和服務(wù)器會(huì)相互交換各自的初始序列號(hào),以保證接下來(lái)的數(shù)據(jù)傳輸能夠按順序接收和處理。這是實(shí)現(xiàn)TCP可靠傳輸?shù)年P(guān)鍵步驟之一。
三次握手的設(shè)計(jì)主要是為了確保在不可靠的網(wǎng)絡(luò)環(huán)境中,TCP連接的建立過程能夠具有可靠性和一致性,并能夠防止?jié)撛诘腻e(cuò)誤連接。
2. 為何 TCP 關(guān)閉連接時(shí)需要四次揮手?
- 保證雙方數(shù)據(jù)完整性:在關(guān)閉連接之前,雙方需要確認(rèn)所有數(shù)據(jù)已經(jīng)被成功接收。第一次揮手時(shí),客戶端發(fā)送 FIN 報(bào)文,表示自己不再發(fā)送數(shù)據(jù),但仍然可以接收數(shù)據(jù)。第二次揮手時(shí),服務(wù)器確認(rèn)收到這個(gè) FIN,并且可以繼續(xù)發(fā)送數(shù)據(jù)。第三次揮手時(shí),服務(wù)器發(fā)送自己的 FIN 報(bào)文,表示自己也不再發(fā)送數(shù)據(jù)。最后,客戶端確認(rèn)服務(wù)器的 FIN,確保雙方都完成了數(shù)據(jù)傳輸。
- 分半關(guān)閉(Half-Close):TCP 連接是全雙工的,這意味著數(shù)據(jù)可以雙向流動(dòng)。四次揮手允許連接的一方關(guān)閉數(shù)據(jù)發(fā)送通道,但仍然可以接收數(shù)據(jù),直到另一方也關(guān)閉發(fā)送通道。因此,四次揮手過程允許雙向關(guān)閉連接,確保雙方都能完成數(shù)據(jù)傳輸。
- 確保完整關(guān)閉:客戶端在進(jìn)入TIME-WAIT狀態(tài)后,會(huì)等待一段時(shí)間以確保服務(wù)器收到了最后的 ACK 報(bào)文。這段時(shí)間可以避免因網(wǎng)絡(luò)延遲等問題導(dǎo)致的重復(fù)數(shù)據(jù)問題,確保連接完全關(guān)閉后再釋放資源。
3. 為何 TIME_WAIT 狀態(tài)需持續(xù) 2MSL 后才能轉(zhuǎn)為 CLOSE 狀態(tài)?
當(dāng) TCP 連接的一方完成連接釋放后,會(huì)進(jìn)入 TIME_WAIT 狀態(tài)。這個(gè)狀態(tài)需要持續(xù) 2 倍的最大段壽命(Maximum Segment Lifetime,MSL)的時(shí)間,這是為了確保在傳輸過程中可能存在的延遲數(shù)據(jù)包能夠被對(duì)方完全接收。只有當(dāng) 2MSL 時(shí)間過去后,確認(rèn)對(duì)方已收到所有數(shù)據(jù),該 TCP 連接才能完全關(guān)閉,進(jìn) 入CLOSE 狀態(tài)。
(1) 確保服務(wù)端能夠接收到客戶端的確認(rèn)應(yīng)答。
如果客戶端在發(fā)送完確認(rèn)應(yīng)答后立即進(jìn)入 CLOSED 狀態(tài),而該應(yīng)答不幸丟失,服務(wù)端在等待超時(shí)后將嘗試重新發(fā)送連接釋放請(qǐng)求。但此時(shí),由于客戶端已經(jīng)關(guān)閉,無(wú)法再作出響應(yīng),這會(huì)導(dǎo)致服務(wù)端無(wú)法正常關(guān)閉 TCP 連接。因此,TIME_WAIT 狀態(tài)的持續(xù)存在,是為了保證服務(wù)端能夠接收到并處理客戶端的確認(rèn)應(yīng)答,從而確保連接的平滑關(guān)閉。
(2) 防止“三次握手”中提及的“已失效的連接請(qǐng)求報(bào)文段”干擾當(dāng)前連接。
當(dāng)客戶端發(fā)送完最后一個(gè)確認(rèn)報(bào)文后,經(jīng)過 2MSL 的時(shí)間間隔,可以確保在本連接持續(xù)時(shí)間內(nèi)產(chǎn)生的所有報(bào)文段都已從網(wǎng)絡(luò)中清除。這樣,新建立的連接就不會(huì)受到舊連接請(qǐng)求報(bào)文的影響。
(3) 為什么是 2MSL?
2MSL 的時(shí)間是從客戶端收到 FIN 報(bào)文段后發(fā)送給服務(wù)器 ACK 開始計(jì)時(shí)的,考慮到重傳的因素,那么就需要服務(wù)器再次給客戶端傳 FIN+ACK 報(bào)文段。
保證在兩個(gè)傳輸方向上的尚未被接收或遲到的報(bào)文段都消失,理論上保證最后一個(gè)報(bào)文可靠到達(dá),就需要 2MSL,一個(gè)方向一個(gè) 1MSL。
4. CLOSE_WAIT 狀態(tài)有什么影響?
當(dāng)服務(wù)器收到客戶端的 FIN,并回復(fù)了 ACK 后,會(huì)進(jìn)入 CLOSE_WAIT 狀態(tài),此時(shí) TCP 鏈接處于半關(guān)閉狀態(tài)。CLOSE_WAIT 狀態(tài)一直存在就說(shuō)明服務(wù)器沒有調(diào)用 close 并沒有發(fā)送 FIN 報(bào)文段。而服務(wù)期長(zhǎng)期保持這個(gè)狀態(tài),就會(huì)一直占用這大量的 socket 文件描述符,大量的 CLOSE_WAIT 狀態(tài)存在就會(huì)導(dǎo)致文件描述符被占用,一些客戶端無(wú)法連接。
5. TIME_WAIT和CLOSE_WAIT的區(qū)別?
CLOSE_WAIT 狀態(tài)是被動(dòng)關(guān)閉的一端在接收到另一端關(guān)閉請(qǐng)求過后并將 ACK 發(fā)送出去后所處的狀態(tài)。這種狀態(tài)表示:收到了對(duì)端關(guān)閉的情況,但是本端還沒有完成工作,未關(guān)閉。
TIME_WAIT 狀態(tài)是主動(dòng)關(guān)閉一端在本端已經(jīng)關(guān)閉的前提下,收到對(duì)端的關(guān)閉請(qǐng)求并且將 ACK 發(fā)送出去所處的狀態(tài)。這種狀態(tài)表示:雙方都已經(jīng)完成工作,只是為了確保遲來(lái)的數(shù)據(jù)報(bào)能被識(shí)別丟棄,可靠的終止 TCP 連接。
6. 為什么連接的時(shí)候是三次握手,關(guān)閉的時(shí)候卻是四次揮手?
因?yàn)楫?dāng)服務(wù)端收到客戶端的 SYN 連接請(qǐng)求報(bào)文后,可以直接發(fā)送 SYN+ACK 報(bào)文。其中 ACK 報(bào)文是用來(lái)應(yīng)答的,SYN 報(bào)文是用來(lái)同步的。
但是關(guān)閉連接時(shí),當(dāng)服務(wù)端收到 FIN 報(bào)文時(shí),很可能并不會(huì)立即關(guān)閉 SOCKET,所以只能先回復(fù)一個(gè) ACK 報(bào)文,告訴客戶端,“你發(fā)的 FIN 報(bào)文我收到了”。只有等到我服務(wù)端所有的報(bào)文都發(fā)送完了,我才能發(fā)送 FIN 報(bào)文,因此不能一起發(fā)送。故需要四步握手。
7. 如果已經(jīng)建立了連接,但是客戶端突然出現(xiàn)故障了怎么辦?
TCP 設(shè)有一個(gè)保活計(jì)時(shí)器,顯然,客戶端如果出現(xiàn)故障,服務(wù)器不能一直等下去,白白浪費(fèi)資源。服務(wù)器每收到一次客戶端的請(qǐng)求后都會(huì)重新復(fù)位這個(gè)計(jì)時(shí)器,時(shí)間通常是設(shè)置為 2 小時(shí),若 2 小時(shí)還沒有收到客戶端的任何數(shù)據(jù),服務(wù)器就會(huì)發(fā)送一個(gè)探測(cè)報(bào)文段,以后每隔 75 分鐘發(fā)送一次。若一連發(fā)送 10 個(gè)探測(cè)報(bào)文仍然沒反應(yīng),服務(wù)器就認(rèn)為客戶端出了故障,接著就關(guān)閉連接。
8. 在三次握手中,SYN 和 ACK 的作用是什么?
在 TCP 的三次握手中,SYN 和 ACK 確保了連接的建立和通信的同步。
- SYN(Synchronize)是 TCP 協(xié)議中的一個(gè)標(biāo)志位,用于在建立連接時(shí)進(jìn)行通信的同步。在三次握手的第一次交互中,客戶端發(fā)送一個(gè) SYN=1,ACK=0 標(biāo)志的數(shù)據(jù)包給服務(wù)端,請(qǐng)求建立連接。這個(gè) SYN 包的作用是向服務(wù)端發(fā)起連接請(qǐng)求,并附帶一個(gè)序列號(hào)(Sequence Number),用于標(biāo)識(shí)后續(xù)發(fā)送的數(shù)據(jù)包。SYN 標(biāo)志位的設(shè)置表示客戶端希望建立一個(gè)新的連接或確認(rèn)一個(gè)連接請(qǐng)求;
- ACK(Acknowledgement)是確認(rèn)標(biāo)志,用于確認(rèn)接收到的數(shù)據(jù)包。在第二次握手中,服務(wù)端收到客戶端的 SYN 包后,會(huì)發(fā)送一個(gè) SYN=1,ACK=1 標(biāo)志的數(shù)據(jù)包給客戶端。這個(gè) SYN+ACK 包的作用是告訴客戶端,服務(wù)端已經(jīng)收到了連接請(qǐng)求,并允許建立連接。同時(shí),ACK=1 表示服務(wù)端對(duì)客戶端發(fā)送的 SYN 包進(jìn)行了確認(rèn)。此外,服務(wù)端也會(huì)發(fā)送自己的序列號(hào)給客戶端,用于后續(xù)的數(shù)據(jù)傳輸。
- 在第三次握手中,客戶端收到服務(wù)端的 SYN+ACK 包后,會(huì)發(fā)送一個(gè) SYN=0,ACK=1 的數(shù)據(jù)包給服務(wù)端。這個(gè) ACK 包的作用是告訴服務(wù)端,客戶端已經(jīng)收到了 SYN+ACK 包,并對(duì)服務(wù)端的 SYN 包進(jìn)行了確認(rèn)。
- 至此,三次握手完成,TCP 連接建立成功,雙方可以開始進(jìn)行數(shù)據(jù)傳輸。
在整個(gè)過程中,SYN 和 ACK 標(biāo)志位確保了連接的建立和通信的同步。SYN 用于發(fā)起連接請(qǐng)求和標(biāo)識(shí)序列號(hào),而ACK 用于確認(rèn)接收到的數(shù)據(jù)包。這種機(jī)制可以有效地確保數(shù)據(jù)的可靠傳輸和連接的穩(wěn)定性。
9. 三次握手過程中可以攜帶數(shù)據(jù)嗎?
在 TCP 的三次握手過程中,SYN 和 SYN+ACK 報(bào)文段是不攜帶數(shù)據(jù)的,它們僅僅用于建立連接時(shí)的同步和確認(rèn)。但是,最后一次的 ACK 報(bào)文段是可以攜帶數(shù)據(jù)的。這是因?yàn)楫?dāng)發(fā)送方收到對(duì)方的 SYN+ACK 報(bào)文段后,連接就已經(jīng)建立了,此時(shí)發(fā)送方就可以立即發(fā)送數(shù)據(jù),而這個(gè)數(shù)據(jù)就可以和 ACK 報(bào)文段一起發(fā)送,從而提高了效率。
雖然第三次握手可以攜帶數(shù)據(jù),但在實(shí)際網(wǎng)絡(luò)編程中,并不推薦這樣做。因?yàn)檫@樣做可能會(huì)帶來(lái)一些問題,比如接收方可能無(wú)法及時(shí)準(zhǔn)備好接收數(shù)據(jù),導(dǎo)致數(shù)據(jù)丟失或亂序。
因此,通常建議將數(shù)據(jù)的發(fā)送放在三次握手完成之后進(jìn)行,以確保數(shù)據(jù)的可靠傳輸。
10. TCP 連接中的半連接隊(duì)列和全連接隊(duì)列是什么?
TCP 連接中的半連接隊(duì)列(也稱為 SYN 隊(duì)列)用于存儲(chǔ)處于 TCP 三次握手過程中第一步的連接請(qǐng)求。
當(dāng)服務(wù)端收到客戶端發(fā)起的 SYN 請(qǐng)求后,內(nèi)核會(huì)把該連接存儲(chǔ)到半連接隊(duì)列中,等待完成三次握手的過程。此時(shí),連接請(qǐng)求還沒有完成握手,因此被認(rèn)為是“半連接”。如果半連接隊(duì)列滿了,新來(lái)的連接請(qǐng)求可能會(huì)被丟棄或者根據(jù)系統(tǒng)配置發(fā)送 RST 報(bào)文。
全連接隊(duì)列就是已經(jīng)完成三次握手,建立起連接的就會(huì)放在全連接隊(duì)列中。
半連接隊(duì)列的主要作用是管理并跟蹤那些尚未完全建立的連接,確保在三次握手完成之前,這些連接請(qǐng)求能夠得到妥善的處理。它是 TCP 協(xié)議保證連接可靠性和性能的重要機(jī)制之一。
需要注意的是,當(dāng)服務(wù)端并發(fā)處理大量請(qǐng)求時(shí),如果 TCP 半連接隊(duì)列過小,就容易出現(xiàn)溢出的情況,導(dǎo)致后續(xù)的請(qǐng)求被丟棄,從而影響服務(wù)端的請(qǐng)求處理能力。因此,合理設(shè)置和調(diào)整半連接隊(duì)列的大小對(duì)于優(yōu)化網(wǎng)絡(luò)性能和提升系統(tǒng)穩(wěn)定性具有重要意義。
11. TCP 連接中 ISN(Initial Sequence Number)是什么?
在 TCP 連接中,ISN(Initial Sequence Number,初始序列號(hào))是每個(gè) TCP 連接在建立時(shí)由 TCP 協(xié)議為每一個(gè)數(shù)據(jù)包所賦予的序列號(hào)。它是 TCP 可靠傳輸?shù)囊粋€(gè)重要組成部分,用于確保數(shù)據(jù)的順序性和完整性。
- 當(dāng) TCP 連接建立時(shí),客戶端和服務(wù)器都會(huì)選擇一個(gè)初始序列號(hào)(ISN)作為它們發(fā)送的第一個(gè)數(shù)據(jù)包的序列號(hào)。這個(gè)序列號(hào)是一個(gè)隨機(jī)值,通常不會(huì)重復(fù),用于標(biāo)識(shí)該連接中的每一個(gè)數(shù)據(jù)包的順序。
- 在數(shù)據(jù)傳輸過程中,TCP 協(xié)議會(huì)根據(jù)數(shù)據(jù)包的發(fā)送順序?yàn)槊總€(gè)數(shù)據(jù)包分配一個(gè)遞增的序列號(hào)。ISN 可以看作是一個(gè) 32 比特的計(jì)數(shù)器,每 4ms 加 1 。
- 通過序列號(hào),接收方可以準(zhǔn)確地按照發(fā)送方的發(fā)送順序來(lái)重組數(shù)據(jù),從而確保數(shù)據(jù)的順序性。
- 此外,序列號(hào)還可以用于檢測(cè)丟失或重復(fù)的數(shù)據(jù)包。當(dāng)接收方發(fā)現(xiàn)數(shù)據(jù)包的序列號(hào)不連續(xù)時(shí),它會(huì)向發(fā)送方發(fā)送一個(gè) ACK(確認(rèn))消息,請(qǐng)求發(fā)送方重傳丟失的數(shù)據(jù)包。同樣地,如果接收方接收到一個(gè)重復(fù)的數(shù)據(jù)包(即具有相同序列號(hào)的數(shù)據(jù)包),它可以通過序列號(hào)來(lái)識(shí)別并丟棄這個(gè)重復(fù)的數(shù)據(jù)包。
因此,ISN 在 TCP 連接確保了數(shù)據(jù)的順序性和完整性,為 TCP 的可靠傳輸提供了基礎(chǔ)。
12. 為什么 TCP 連接建立需要發(fā)送序列號(hào)?
TCP 連接建立需要發(fā)送序列號(hào)的原因主要有以下幾點(diǎn):
- 確保數(shù)據(jù)的順序性: TCP 是一個(gè)面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。在 TCP 通信中,發(fā)送方和接收方都需要按照數(shù)據(jù)的發(fā)送順序來(lái)接收和處理數(shù)據(jù)。序列號(hào)用于標(biāo)識(shí)每一個(gè)發(fā)送的數(shù)據(jù)包,確保接收方能夠按照正確的順序重組數(shù)據(jù)。
- 實(shí)現(xiàn)可靠傳輸: TCP 通過序列號(hào)來(lái)實(shí)現(xiàn)數(shù)據(jù)的可靠傳輸。當(dāng)接收方收到數(shù)據(jù)包后,會(huì)向發(fā)送方發(fā)送一個(gè)確認(rèn)(ACK)消息,告知已經(jīng)成功接收到的數(shù)據(jù)包的序列號(hào)。如果發(fā)送方在某個(gè)時(shí)間點(diǎn)內(nèi)沒有收到某個(gè)數(shù)據(jù)包的 ACK,它會(huì)認(rèn)為該數(shù)據(jù)包丟失,并重新發(fā)送該數(shù)據(jù)包。序列號(hào)使得發(fā)送方能夠準(zhǔn)確地知道哪些數(shù)據(jù)包已經(jīng)成功發(fā)送并被接收,哪些數(shù)據(jù)包需要重傳。
- 處理網(wǎng)絡(luò)中的數(shù)據(jù)包亂序: 在網(wǎng)絡(luò)傳輸過程中,由于網(wǎng)絡(luò)擁塞、路由變化等原因,數(shù)據(jù)包可能會(huì)亂序到達(dá)接收方。通過序列號(hào),接收方能夠識(shí)別并重新排序這些亂序的數(shù)據(jù)包,確保數(shù)據(jù)的完整性和正確性。
- 流量控制和擁塞控制: TCP 還利用序列號(hào)來(lái)實(shí)現(xiàn)流量控制和擁塞控制。發(fā)送方會(huì)根據(jù)接收方的確認(rèn)消息和當(dāng)前的網(wǎng)絡(luò)狀況來(lái)調(diào)整發(fā)送速率,以避免網(wǎng)絡(luò)擁塞和數(shù)據(jù)丟失。序列號(hào)在這個(gè)過程中起到了關(guān)鍵作用,幫助發(fā)送方和接收方協(xié)調(diào)數(shù)據(jù)的發(fā)送和接收。
TCP 連接建立需要發(fā)送序列號(hào)是為了確保數(shù)據(jù)的順序性、實(shí)現(xiàn)可靠傳輸、處理網(wǎng)絡(luò)中的數(shù)據(jù)包亂序以及實(shí)現(xiàn)流量控制和擁塞控制。這些功能共同保證了 TCP 能夠提供高效、可靠的數(shù)據(jù)傳輸服務(wù)。
13. 在 TCP 通信中,如果一方突然崩潰,另一方如何知道?
在 TCP 通信中,如果一方突然崩潰(例如,由于硬件故障、操作系統(tǒng)崩潰或應(yīng)用程序異常終止),另一方通常通過以下幾種機(jī)制來(lái)檢測(cè)這種情況:
- 心跳機(jī)制(Keep-Alive): TCP 本身并沒有一個(gè)顯式的“心跳”機(jī)制,但許多操作系統(tǒng)和應(yīng)用程序?qū)訁f(xié)議實(shí)現(xiàn)了這種機(jī)制。通過定期發(fā)送小的數(shù)據(jù)包(通常稱為“探測(cè)包”或“心跳包”),接收方可以通知發(fā)送方它仍然存活并且連接仍然有效。如果發(fā)送方在一段時(shí)間內(nèi)沒有收到響應(yīng),它可能會(huì)認(rèn)為接收方已經(jīng)崩潰,并關(guān)閉連接。
- 超時(shí)重傳和重試: TCP 使用超時(shí)重傳機(jī)制來(lái)處理丟失的數(shù)據(jù)包。當(dāng)發(fā)送方發(fā)送一個(gè)數(shù)據(jù)包后,它會(huì)等待一個(gè)確認(rèn)(ACK)。如果在一定的超時(shí)時(shí)間內(nèi)沒有收到 ACK,發(fā)送方會(huì)重傳該數(shù)據(jù)包。如果經(jīng)過多次重傳仍然未收到確認(rèn),發(fā)送方會(huì)認(rèn)為連接已經(jīng)中斷,并關(guān)閉連接。同樣,接收方在收到亂序的數(shù)據(jù)包或數(shù)據(jù)包丟失時(shí),也會(huì)通過發(fā)送重復(fù) ACK 或通知發(fā)送方進(jìn)行快速重傳來(lái)處理。
- 應(yīng)用層協(xié)議: 除了 TCP 本身的機(jī)制外,應(yīng)用層協(xié)議(如 HTTP、FTP 等)通常也會(huì)實(shí)現(xiàn)自己的連接管理和錯(cuò)誤處理機(jī)制。這些協(xié)議可能會(huì)定義特定的消息或命令來(lái)通知對(duì)方連接已經(jīng)中斷,或者通過超時(shí)和重試策略來(lái)處理突然的崩潰。
- 操作系統(tǒng)和網(wǎng)絡(luò)棧的通知: 在某些情況下,當(dāng)一方崩潰時(shí),操作系統(tǒng)或網(wǎng)絡(luò)??赡軙?huì)向另一方發(fā)送一個(gè)特殊的信號(hào)或錯(cuò)誤消息。例如,當(dāng) TCP 連接的一方異常終止時(shí),操作系統(tǒng)可能會(huì)向另一方發(fā)送一個(gè) RST(重置)數(shù)據(jù)包來(lái)關(guān)閉連接。
由于網(wǎng)絡(luò)的復(fù)雜性和不確定性,有時(shí)候即使一方崩潰,另一方也可能無(wú)法立即檢測(cè)到。這取決于網(wǎng)絡(luò)狀況、操作系統(tǒng)的實(shí)現(xiàn)以及應(yīng)用層協(xié)議的設(shè)計(jì)。因此,在設(shè)計(jì)和實(shí)現(xiàn)基于 TCP 的應(yīng)用程序時(shí),應(yīng)該考慮到這種可能性,并采取相應(yīng)的錯(cuò)誤處理和恢復(fù)策略。