面試問題:TCP 和 UDP 差別是什麼? TCP 連線為什麼是三次握手而不是兩次或四次?
2025.05.08
一、面試官:什麼是TCP的三次握手?三次握手的過程是怎麼樣的?為什麼需要三次握手而不是兩次或四次?
TCP(傳輸控制協定)是一種連線導向的、可靠的傳輸層協定。在建立連線時,TCP使用三次握手(Three-way Handshake)機制來確保通訊雙方能夠同步彼此的序號,並確認雙方都具備發送和接收資料的能力 。
1. 三次握手的具體過程
(1) 第一次握手
客戶端向伺服器發送一個SYN(同步)包,表示希望建立連線。這個SYN套件中包含一個隨機產生的初始序號(ISN, Initial Sequence Number),用於後續資料傳輸的編號。發送完成後,客戶端進入SYN_SENT狀態,等待伺服器的回應
(2) 第二次握手
伺服器收到客戶端的SYN包後,會回覆客戶端一個SYN+ACK包。其中,SYN表示伺服器同意建立連接,ACK是對客戶端SYN包的確認,確認號碼為客戶端的初始序號加1。同時,伺服器也會產生自己的初始序號,並將其包含在SYN套件中。此時,伺服器進入SYN_RCVD狀態 。
(3) 第三次握手
用戶端收到伺服器的SYN+ACK包後,會再傳送一個ACK包,作為伺服器SYN包的確認。這個ACK包的確認號碼是伺服器的初始序號加1。發送完成後,客戶端和伺服器都進入ESTABLISHED狀態,連線正式建立,雙方可以開始傳輸資料 。
2. 為什麼需要三次握手而非兩次或四次?
(1) 同步雙方的初始序號
TCP協定的通訊雙方都必須維護一個序號,這是確保可靠傳輸的關鍵因素。序號在TCP連線中扮演了重要角色,它具有以下作用:
接收者可以消除重複的數據,確保數據的準確性。
接收方可以依照序號的順序接收資料包,確保資料的完整性。
序號可以標識已經被對方接收的資料包,實現可靠的資料傳輸。
因此,在建立TCP連線時,客戶端發送帶有初始序號的SYN封包,並需要伺服器回覆一個ACK封包,表示成功接收了客戶端的SYN封包。然後,伺服器發送帶有初始序號的SYN封包給客戶端,並等待客戶端的應答,這樣一來一回,才能確保雙方的初始序號能夠可靠地同步。
雖然四次握手也可以實現可靠地同步雙方的初始序號,但由於第二步和第三步可以合併為一步,所以最終演變成了三次握手。而兩次握手只能保證一方的初始序號被對方成功接收,無法保證雙方的初始序號都能被確認接收。因此,三次握手是為了確保TCP連接的穩定性和可靠性而採取的最佳選擇。
(2) 防止舊的重複連接初始化造成混亂
在網路通訊中,封包可能會因為網路擁塞、路由問題或其他原因而延遲到達。這些延遲的資料包被稱為「歷史資料包」或「舊資料包」。如果TCP只使用兩次握手,伺服器無法區分目前收到的SYN套件是新的連線請求,還是一個延遲到達的舊連線請求 。
假設以下場景:
客戶端發送了一個SYN包(連線請求),但由於網路延遲,這個SYN包沒有及時到達伺服器。
客戶端由於逾時未收到伺服器的回應,重新發送了一個新的SYN套件(新的連線請求)。
如果採用兩次握手,伺服器收到新的SYN包後,回覆SYN+ACK包,並認為連線已建立。
隨後,舊的SYN包延遲到達伺服器。由於伺服器只進行兩次握手,它會將這個舊的SYN套件誤認為是一個新的連線請求,並回覆SYN+ACK套件,進而為這個不存在的連線分配資源 。
三次握手如何避免這個問題?在三次握手中:
當伺服器收到SYN套件後,會回覆SYN+ACK套件(第二次握手),但不會立即進入連線狀態。
只有當客戶端收到SYN+ACK包並回覆ACK包(第三次握手)後,伺服器才會確認這是一個有效的連線。
如果舊的SYN包延遲到達伺服器,伺服器會回覆SYN+ACK包,但用戶端不會發送最終的ACK包,因為用戶端並沒有發起這個舊的連線請求。因此,伺服器會丟棄這個無效的連接,避免資源浪費 。
(3) 確認雙方的收發能力
三次握手確保了雙方都能正常發送和接收資料。例如,客戶端透過第二次握手確認伺服器能接收到自己的套件;伺服器透過第三次握手確認客戶端能接收到自己的套件 。
二、面試官追問:第三次握手過程中,如果客戶端的ACK未送達伺服器,會發生什麼事?如果已經建立了連接,但客戶端出現了故障怎麼辦?
在TCP三次握手過程中,如果第三次握手的ACK包未送達伺服器,會發生以下情況:
1. 伺服器的行為
伺服器在發送SYN+ACK套件後,會進入SYN_RCVD狀態,等待客戶端的ACK確認。
如果伺服器沒有收到客戶端的ACK包,它會認為自己的SYN+ACK包可能遺失,因此會根據TCP的逾時重傳機制,重新傳送SYN+ACK包。
通常情況下,伺服器會嘗試重傳SYN+ACK套件最多5次(具體次數取決於實作),每次重傳的時間間隔會逐漸增加(例如3秒、6秒、12秒等)。
如果經過多次重送後仍沒有收到客戶端的ACK確認,伺服器會放棄建立連接,並進入CLOSED狀態,釋放相關資源。
在服務端進入CLOSED狀態之後,如果客戶端向伺服器發送數據,伺服器會以RST包應答。
2. 客戶端的行為
用戶端在發送ACK包後,會進入ESTABLISHED狀態,認為連線已經建立。
如果客戶端隨後開始向伺服器發送數據,而伺服器尚未收到ACK確認,伺服器在收到資料包時會檢查其中的ACK標誌位元。如果封包包含有效的ACK訊息,伺服器會將其視為對SYN+ACK的確認,並完成連線的建立。
3. 如果已經建立了連接,但客戶端出現了故障怎麼辦?
在TCP協定中,若已建立連線但客戶端發生故障,伺服器端會透過保活機制(Keepalive)偵測連線狀態,並採取對應措施釋放資源。以下是詳細分析:
(1) TCP連線故障處理機制
保活機制(Keepalive):
觸發條件:當連線長時間無資料互動時(預設2小時),伺服器會啟動保活探測。
探測過程:伺服器每隔75秒發送一次探測封包(空資料包),若連續10次(約11分鐘)未收到客戶端回應,則判定連線失效。
結果處理:伺服器主動關閉連接,釋放佔用的連接埠和記憶體資源,避免資源洩漏。
(2) 潛在問題與解決方案
保活機制缺陷:
偵測延遲:預設11分鐘的偵測週期較長,可能無法滿足即時性要求。
最佳化建議:在應用層實現心跳機制(如HTTP長輪詢、WebSocket),透過自訂協定定期傳送心跳包,縮短故障偵測時間。
資源競爭風險:
場景:若客戶端崩潰前未釋放連接,伺服器可能因資源耗盡(如TIME_WAIT狀態堆積)無法建立新連線。
優化建議:
調整核心參數(如`net.ipv4.tcp_keepalive_time`)縮短保活間隔。
使用連接池技術重複使用連接,減少頻繁建立/釋放的開銷。
三、面試官追問:TCP四次揮手的過程是怎麼樣的?為什麼不能把伺服器發送的ACK和FIN合併起來,變成三次揮手?
TCP斷開連線需要透過四次揮手的方式。雙方都有能力主動斷開連接,一旦斷開連接,主機中的各種「資源」將被釋放。
TCP連線是全雙工的,因此每個方向都必須單獨進行關閉。首先進行關閉的一方將執行主動關閉,而另一方則執行被動關閉。
整個過程通常涉及四個步驟,每個步驟都透過交換TCP封包文段來完成。而且每次揮手客戶端和服務端都會進入到對應的狀態 (FIN_WAIT_1、FIN_WAIT_2、CLOSED_WAIT、LAST_ACK 和 TIME_WAIT)。
1. 四次揮手詳細步驟
(1) 第一次揮手:主動關閉方發送FIN報文
流程:主動關閉方(通常是客戶端)發送一個FIN(Finish)報文段,表示它已經沒有資料要發送了,希望關閉連接,但此時主動關閉方還能接受資料。此時,主動關閉方進入FIN_WAIT_1狀態,等待被動關閉方的確認。
報文段內容:FIN報文段中,FIN標誌位元被設定為1,同時可能包含一個序號(seq),用於識別該封包在資料流中的位置。
(2) 第二次揮手:被動關閉方回應ACK報文
流程:被動關閉方(通常是伺服器)收到FIN報文段後,發送一個ACK(Acknowledgment)封包段作為回應,表示已經收到了關閉請求。此時,被動關閉方進入CLOSE_WAIT狀態,表示它已經準備好關閉連接,但可能還需要處理剩餘的資料。主動關閉方收到ACK報文段後,進入FIN_WAIT_2狀態。在這個階段,如果服務端處理好了資料(如果有的話)會將資料傳送給客戶端。
報文段內容:ACK報文段中,ACK標誌位元被設定為1,確認序號(ack)為收到的FIN報文段的序號加1,表示對FIN報文段的確認。
(3) 第三次揮手:被動關閉方發送FIN報文
流程:被動關閉方在處理完剩餘資料後,發送FIN報文段,表示它也沒有資料要傳送了,要求關閉連線。此時,被動關閉方進入LAST_ACK狀態,等待主動關閉方的確認。
報文段內容:FIN報文段中,FIN標誌位元被設定為1,同時可能包含一個序號(seq),用於識別該封包在資料流中的位置。
(4) 第四次揮手:主動關閉方回應ACK訊息並進入TIME_WAIT狀態
流程:主動關閉方收到被動關閉方的FIN報文段後,發送一個ACK報文段作為回應,表示已經收到了關閉請求。此時,主動關閉方進入TIME_WAIT狀態,等待一段時間(通常為2MSL,即最大段生存期的兩倍),以確保被動關閉方收到了最終的ACK報文段。如果被動關閉方沒有收到ACK報文段,它會重新發送FIN報文段,主動關閉方則可以再次發送ACK報文段。等待時間結束後,主動關閉方進入CLOSED狀態,連線正式關閉。被動關閉方收到ACK報文段後,也立即進入CLOSED狀態。
報文段內容:ACK報文段中,ACK標誌位元被設定為1,確認序號(ack)為收到的FIN報文段的序號加1,表示對FIN報文段的確認。
2. 為什麼不能將ACK和FIN合併為三次揮手?
為了更好地理解為什麼揮手需要四次,讓我們再來回顧一下雙方發出FIN包的過程。這樣我們就能理解為什麼需要四次揮手了。
在關閉連線時,當客戶端向服務端發送FIN時,這僅表示客戶端不再發送資料了,但是它仍然可以接收資料。
當服務端收到客戶端的FIN報文時,它會先回覆一個ACK應答報文。然而,服務端可能還有資料需要處理和傳送,所以它會等待直到它不再發送資料時,才會發送FIN封包給客戶端,表示同意現在關閉連線。
透過上述過程,我們可以看出,服務端通常需要等待完成資料的發送和處理,所以服務端的ACK和FIN通常會分開發送,這就導致了比三次握手多了一次揮手的過程。
四、面試官追問:為什麼主動關閉方最後一次揮手後會進入TIME_WAIT狀態而不是直接釋放資源?為什 TIME_WAIT 狀態持續的時間是2MSL?
TIME_WAIT 狀態的存在是為了確保網路連線的可靠關閉。只有主動發起關閉連線的一方(即主動關閉方)才會有 TIME_WAIT 狀態。
客戶端進入 TIME_WAIT 狀態是 TCP 協定可靠性和健壯性設計的重要體現,其核心意義體現在以下關鍵方面:
1. 確保可靠終止連接
避免資料遺失:在 TCP 四次揮手過程中,客戶端發送最後一個 ACK 確認訊息後進入 TIME_WAIT 狀態,等待 2 倍最大報文段生存時間(2MSL)。若該 ACK 遺失,服務端會重送 FIN 封包,用戶端可在 TIME_WAIT 期間重新傳送 ACK,確保服務端已正確關閉連線。
處理延遲或重傳封包:網路中可能存在延遲或重傳的封包,TIME_WAIT 狀態確保這些封包在連線完全終止前被丟棄,避免干擾後續新連線。
2. 防止連線復用衝突
避免連接埠和位址混淆:TCP 連線由四元組(來源 IP、來源連接埠、目的 IP、目的連接埠)唯一識別。 TIME_WAIT 狀態確保在舊連線完全終止前,相同的四元組不會被新連線重複使用。若新連接復用舊連接的位址和端口,舊連接的延遲封包可能被誤認為新連接的數據,導致數據混亂。
維持連線唯一性:透過等待 2MSL,TIME_WAIT 狀態確保舊連線的封包在網路中自然消失,從而確保新連線的獨立性和正確性。
為什 TIME_WAIT 狀態持續的時間是2MSL?
MSL是封包在網路中存活的最長時間,超過該時間後,封包將被丟棄。不同作業系統或網路設備對MSL的定義可能有差異(如RFC 793建議MSL為2分鐘,但實際上可能更短)。
如上所述,TCP封包在網路中可能因延遲、路由重傳等原因滯留,最長可達MSL時間。若主動關閉方在TIME_WAIT階段未等待足夠時間,新建立的連線可能重複使用相同的四元群組(來源IP、來源連接埠、目的IP、目的連接埠),導致滯留的舊連線訊息誤認為新連線數據,引發資料混亂或協定錯誤。
等待2MSL可確保所有舊連線封包因逾時而被丟棄,避免對新連線造成乾擾。例如,若MSL為30秒,則2MSL為60秒,足以涵蓋網路中可能的最長滯留時間。
雖然TIME_WAIT狀態會佔用連接埠和系統資源,但2MSL的等待時間是協定可靠性的必要代價。在高並發情境下,可透過調整系統參數(如縮短TIME_WAIT時間或重複使用TIME_WAIT連線)最佳化資源利用率,但需謹慎權衡可靠性與效能。
五、面試官追問:TCP和UDP協議的差別是什麼?它們的適用場景分別有哪些?
TCP是一種面向連接、可靠的、基於位元組流的傳輸層通訊協定。
面向連接:面向連接意味著TCP通信是一對一的,即點對點端到端的通信,不像UDP可以同時向多個主機發送訊息,因此無法實現一對多的通信。
可靠的:TCP的可靠性保證了無論網路連結中發生何種變化,TCP都能確保封包的可靠傳輸到達接收端,這也使得TCP的協定封包格式相比UDP更為複雜。
基於位元組流:基於位元組流的特性使得TCP可以傳輸任意大小的訊息,而且保證了訊息的有序性,前一個訊息未被完全接收,即使後面的位元組已經接收,TCP也不會將其交付給應用層處理。同時對於重複的封包會自動丟棄。
UDP(User Datagram Protocol)是一種面向無連接的通訊協議,相較於TCP,UDP不提供複雜的控制機制。 UDP協定允許應用程式在不建立連線的情況下直接傳送封裝的IP資料包。開發人員選擇使用UDP而不是TCP時,應用程式與IP直接進行通訊。
1. 核心特性對比
2. 關鍵差異解析
(1) 可靠性 vs 高效性
TCP:透過確認機制(ACK)、重傳(Retransmission)、序號(Sequence Number)等技術確保資料可靠傳輸,但會增加延遲和開銷。
UDP:僅提供「盡力而為」的傳輸,不保證資料完整性,但因無需等待確認,可實現更低延遲的即時通訊。
(2) 連線建立 vs 即發即走
TCP:需透過三次握手建立連線(SYN→SYN+ACK→ACK),類似打電話前先撥號確認;關閉時需四次揮手(FIN→ACK→FIN→ACK),類似掛電話前的禮貌道別。
UDP:直接發送資料包,無需任何連線建立過程,類似寫信無需確認收件人是否在線上。
(3) 性能開銷對比
TCP:頭部包含序號、確認號、視窗大小等字段,共20位元組基礎開銷,複雜場景可能擴展至60位元組。
UDP:頭部僅包含來源連接埠、目的連接埠、長度、校驗和等8位元組字段,開銷極低。
3. 典型應用場景
(1) TCP適用場景
需要高可靠性的應用:如HTTP/HTTPS(網頁)、FTP(檔案傳輸)、SMTP(郵件)、SSH(遠端登入)。
資料完整性敏感的場景:如銀行交易、資料庫同步。
(2) UDP適用場景
即時性要求高的應用:如視訊直播(允許少量丟包)、線上遊戲(低延遲比丟包更重要)。
廣播/群播通訊:如視訊會議、物聯網設備群控。
簡單請求-回應模式:如DNS查詢(通常單包即可完成)。
自訂協定設計:如QUIC協定(Google基於UDP開發,融合TCP可靠性)。
4. 優缺點總結
總結:TCP與UDP的選擇本質是「可靠性」與「效率」的權衡。 TCP適用於資料完整性要求嚴苛的場景,而UDP更適合即時性優先或簡單通訊需求的場景。實際開發中,可依業務特性選擇協議,或透過混合方案兼顧兩者優勢。