[TCP] 2. 為什麼要知道 TCP 三次握手?三次握手過程為何?
為什麼知道 TCP handshake 很重要?
- 前端面試必考
- 知道 TCP handshake 過程很複雜,每次建立所要花的時間和代價都很大,可以的話盡量減少 TCP handshake,以減少 network request 時間
為什麼要握手?
在軟體中,handshake 表示一個信號 (signal),表示 2 台設備或程式要進行身份驗證 (authenticate) or 合作 (coordinate) (詳見 Wiki - Handshake (computing) - Wikipedia )
當我們要握手時,身為 Client 的我們就是希望能與 Server 交互合作,那我們就要先驗明彼此的身份,並確定雙方能有效地交換資料和溝通
三次握手的詳細過程是什麼?
有三次握手的過程,分別是:
nth 握手 | 目的 |
---|---|
1st | Client 想測試 Server 的接收能力 |
2nd | |
3rd | Client 讓 Server 知道:我能成功收到且正確的讀取你的訊息 |
這就好比你在路上跟一個女生要了 Line,然後,然後想測試看看你傳訊息「你好」給她,她能不能正常回你, 而不是用機器人自動回覆「我要去洗澡喔」或是「你幫我去某某某網站幫我衝人氣好嗎?」,然後你也要回傳訊息給她,讓她知道你可以正常地跟她溝通
真實世界 | TCP handshake | |
---|---|---|
1st | 你發訊息「安安,我是 Jason,妳好嗎?」給她,測試她會不會回你 line | Client 想測試 Server 的接收能力 |
2nd | 她說「安安啊,我是 Ketty,你好嗎?」給你,表示她有讀懂你的訊息,且正常回你 | Server 讓 Client 知道,我能成功收到且正確的讀取你的訊息,並想測試 Client 的接收能力 |
3rd | 你說「我很好,謝謝」讓他知道你有看懂她的訊息 | Client 讓 Server 知道,我能成功收到且正確的讀取你的訊息 |
1st handshake
1st handshake 有 1 個目的:
Client 想測試 Server 的接收能力
Clinet 發送 SYN segment 給 Server,希望建立連結,並測試 Server 的接收能力
Synchronize Sequence Numbers,目的為確認雙方 sequence number 相同的資料
傳送的資料:
- 1
SYN
segment,其 seq num = x
Client 狀態:CLOSED -> SYN_SENT
Server 狀態:LISTEN -> SYN_RCVD
2nd handshake
2nd handshake 有 2 個目的:
1. Server 讓 Client 知道:我能成功收到且正確的讀取你的訊息
2. Server 想測試 Client 的接收能力
1. Server 讓 Client 知道:我能成功收到且正確的讀取你的訊息
Server 接收到 Client 資料,成功讀取後,會傳送另一包資料給 Client,告訴 Client 我成功收到你的資料,”成功“ 在這有 2 個含義:
- 我 ”收到“ Client 的資料
- 我 "正確的讀取" Client 的資料
故 Server 會對應 Client 傳送的資料回傳相關的結果,這裡回傳 ack = seq + 1
傳送的資料:
- 1
ACK
segment,其 ack num = x + 1
2. Server 想測試 Client 的接收能力
跟 1st handshake 的過程一樣,但傳送不同的 sequenceNumber
傳送的資料:
- 1
SYN
segment,其 seq num = y
Client 狀態:SYN_SENT -> ESTABLISHED
Server 狀態:SYN_RCVD
3rd handshake
3rd handshake 有 1 個目的:
Client 讓 Server 知道:我能成功收到且正確的讀取你的訊息
傳送的資料:
- 1
ACK
segment, 其 ack num = y + 1
Client 狀態:ESTABLISHED
Server 狀態:SYN_RCVD -> ESTABLISHED
這 3 次 handshake 後,Client 和 Server 就能保證彼此的接收能力都是正常的了
其他問題
為什麼要三次握手,兩次不行嗎?
如果少掉 3rd handshake,Server 就無法確認 Client 的接收能力是正常的, 那就無法穩定的傳輸,TCP protocal 的目的也就沒達成
握手沒成功會怎樣嗎?
若握手沒成功,當 Client 發現 Server 沒有回傳 ACK segment,
就會重發 (retransmission)
重發的次數由 tcp_syn_retries
參數決定,默認是 6 次
net.ipv4.tcp_syn_retries = 6
重試的過程:
- step 1:1s 後 Server 沒回傳 ACK,Client 重傳 SYN
- step 2:若 Client 還是沒收到 ACK,重複步驟 1,但等待時間為 2s
- step 3:若 Client 還是沒收到 ACK,重複步驟 1,但等待時間為 4s
- step 4:若 Client 還是沒收到 ACK,重複步驟 1,但等待時間為 8s
- step 5:若 Client 還是沒收到 ACK,重複步驟 1,但等待時間為 16s
- step 6:若 Client 還是沒收到 ACK,重複步驟 1,但等待時間為 32s
- setp 7:若 Client 還是沒收到 ACK,終止 3 way handshake
即當 Server 沒有回傳 ACK,Client 會等待 2^n s 後重發,最多重發 6 次,若最後仍沒收到,就會終止傳輸的建立,全部的等待時間為:
1 + 2 + 4 + 8 + 16 + 32 = 127
故若等了 2 分鐘還是無法建立成功,就會終止
結論
- 知道為什麼要建立 TCP handshake,是為了雙方知道彼此能正常接收和傳輸,且三次是最精簡的步驟
- 知道 Server 和 Client 怎麼確保對方的接收和傳輸的流程
- 知道握手過程失敗,會有 retransmission 的行為,持續 2 分鐘,若還是沒有成功就會終止
參考資訊
- Everything You Always Wanted to Know About TCP But Too Afraid to Ask (bytebytego.com)
- 两张动图-彻底明白TCP的三次握手与四次挥手tcp三次握手小书go的博客-CSDN博客
- 面试官,不要再问我三次握手和四次挥手 | 猿人谷 (yuanrengu.com)