當(dāng)面試官問(wèn):為什么是 TCP 三次握手?不是兩次、四次?
嗨,我是勾勾。

最近是面試旺季,在面試過(guò)程中,面試者經(jīng)常被問(wèn)到一個(gè)知識(shí)點(diǎn):TCP 三次握手。
什么是三次握手
三次握手(Three-way Handshake)其實(shí)就是指建立一個(gè) TCP 連接時(shí),需要客戶端和服務(wù)器總共發(fā)送 3 個(gè)包。
進(jìn)行三次握手的主要作用就是為了確認(rèn)雙方的接收能力和發(fā)送能力是否正常,指定自己的初始化序列號(hào)為后面的可靠性傳送做準(zhǔn)備。實(shí)質(zhì)上其實(shí)就是連接服務(wù)器指定端口,建立 TCP 連接,并同步連接雙方的序列號(hào)和確認(rèn)號(hào),交換 TCP 窗口大小信息。
剛開(kāi)始客戶端處于 Closed 的狀態(tài),服務(wù)端處于 Listen 狀態(tài)。
三次握手流程
進(jìn)行三次握手的流程大致如下:
第一次握手:客戶端給服務(wù)端發(fā)一個(gè) SYN 報(bào)文,并指明客戶端的初始化序列號(hào) ISN。此時(shí)客戶端處于 SYN_SENT 狀態(tài)。
注意:首部的同步位 SYN=1,初始序號(hào) seq=x,SYN=1 的報(bào)文段不能攜帶數(shù)據(jù),但要消耗掉一個(gè)序號(hào)。
第二次握手:服務(wù)器收到客戶端的 SYN 報(bào)文之后,會(huì)以自己的 SYN 報(bào)文作為應(yīng)答,并且也是指定了自己的初始化序列號(hào) ISN(s)。同時(shí)會(huì)把客戶端的 ISN + 1 作為 ACK 的值,表示自己已經(jīng)收到了客戶端的 SYN,此時(shí)服務(wù)器處于SYN_RCVD的狀態(tài)。
在確認(rèn)報(bào)文段中 SYN=1,ACK=1,確認(rèn)好 ack = x+1,初始序號(hào) seq = y。
第三次握手:客戶端收到 SYN 報(bào)文之后,會(huì)發(fā)送一個(gè) ACK 報(bào)文。當(dāng)然,也是一樣把服務(wù)器的 ISN + 1 作為 ACK 的值,表示已經(jīng)收到了服務(wù)端的 SYN 報(bào)文,此時(shí)客戶端處于 ESTABLISHED 狀態(tài)。服務(wù)器收到 ACK 報(bào)文之后,也處于 ESTABLISHED 狀態(tài)。此時(shí),雙方已建立起了連接。
確認(rèn)報(bào)文段 ACK=1,確認(rèn)好 ack=y+1,序號(hào) seq=x+1(初始為 seq=x,第二個(gè)報(bào)文段所以要+1),ACK報(bào)文段可以攜帶數(shù)據(jù),不攜帶數(shù)據(jù)則不消耗序號(hào)。
發(fā)送第一個(gè) SYN 的一端將執(zhí)行主動(dòng)打開(kāi)(active open),接收這個(gè) SYN 并發(fā)回下一個(gè) SYN 的另一端執(zhí)行被動(dòng)打開(kāi)(passive open)。
在 socket 編程中,客戶端執(zhí)行 connect() 時(shí),將觸發(fā)三次握手。

為什么需要三次握手,兩次不行嗎?
弄清這個(gè)問(wèn)題,我們需要先弄明白三次握手的目的是什么,能不能只用兩次握手來(lái)達(dá)到同樣的目的。
第一次握手:客戶端發(fā)送網(wǎng)絡(luò)包,服務(wù)端收到了。
這樣服務(wù)端就能得出結(jié)論:客戶端的發(fā)送能力、服務(wù)端的接收能力是正常的。
第二次握手:服務(wù)端發(fā)包,客戶端收到了。
這樣客戶端就能得出結(jié)論:服務(wù)端的接收、發(fā)送能力,客戶端的接收、發(fā)送能力是正常的。不過(guò)此時(shí)服務(wù)器并不能確認(rèn)客戶端的接收能力是否正常。
第三次握手:客戶端發(fā)包,服務(wù)端收到了。
這樣服務(wù)端就能得出結(jié)論:客戶端的接收、發(fā)送能力正常,服務(wù)器自己的發(fā)送、接收能力也正常。
因此,需要三次握手才能確認(rèn)雙方的接收與發(fā)送能力是否正常。
推薦閱讀:
從理解 React 框架開(kāi)始,開(kāi)啟金三銀四面試之旅。
點(diǎn)個(gè)“在看”和“贊”吧,
畢竟我是要成為前端網(wǎng)紅的人。
