目錄
- 名詞解釋
- TCP的三次握手
- TCP建立鏈接的步驟
- TCP的三次握手步驟
- 思考:TCP握手爲什麼不是兩次 or 四次?
- TCP的四次揮手
- TCP斷開鏈接的步驟
- TCP的四次揮手步驟
- 思考:爲什麼斷開鏈接的時候要多一個步驟2呢?
- 思考:爲什麼最後客戶端確認斷開鏈接之後還要等待2WSL呢?
- 面試題:TCP爲什麼是3次握手,4次揮手?
這是一個計算機網絡中一個很熱門,很基礎的問題,也是面試常考的一個題,如果你會那不稀奇,如果你不會,那就會涼涼。我這裏來對我學的東西做一個整理,看完時候對這裏的知識應該會很清晰。首先先來名詞解釋,如果遇到不清晰的名詞,記得反過頭來看。
名詞解釋
TCP
:TCP
在計算機網絡模型的傳輸層,對應的是主機到主機的傳輸,爲應用間通信提供能力。TCP
是一個雙工協議,數據任何時候都可以雙向傳輸,這就意味着客戶端和服務端可以平等地發送、接收信息。鏈接:是傳輸層的概念,鏈接是一種傳輸數據的行爲,是網絡行爲狀態的記錄。在傳輸之前,建立一個鏈接,就是在數據收發雙方的內存中都建立一個用於維護數據傳輸狀態的對象,裏面記錄了雙方的
IP
和端口號,狀態是怎樣,傳輸速度是如何等。雙工/單工:
名稱 | 概念 | 線路數量 |
---|---|---|
單工 | 在任何一個時刻,如果數據只能單向發送 | 只需1條( =1 ) |
半雙工 | 在某個時刻數據可以向一個方向傳輸,也可以向另一個方向反方向傳輸,而且交替進行 | 至少 1 條( >= 1 ) |
全雙工 | 任何時刻數據都可以雙向收發 | 大於 1 條( >1 ) |
-
握手:
TCP
的握手目的是爲了建立穩定的鏈接通道。 -
揮手:
TCP
的揮手目的是爲了斷開鏈接。 -
WSL(Maximum Segment Lifetime)
:報文最大生存時間,TCP允許不同的實現可以設置不同的WSL值。 -
seq
序號:用來標識從TCP
源端向目的端發送的字節流,發起方發送數據時對此進行標記📌。 -
ack
確定序號:只有ACK
標誌爲1時,確認序號字段纔有效,ack = seq + 1
-
標誌位:
-
SYN(Synchronization)
:一個Host
主動向另一個Host
發起連接,請求同步。 -
ACK(Acknowledgement)
:因爲要保持連接和可靠性約束,TCP
協議要保證每一條發出的數據必須給返回。接收方收到數據後,都需要給發送方一個響應確認序號有序。 -
RST(Reset)
:重置鏈接 -
FIN(Finish)
:一個Host
主動斷開請求,請求完成 -
PSH(Push)
:一個Host
給另一個Host
發送數據,數據推送 - ...
-
TCP的三次握手
TCP
的三次握手,相對來說是一個比較完整的機制,旨在建立穩定的傳輸通道。
TCP建立鏈接的步驟
下面來看一下TCP
建立鏈接的6個步驟:
- 客戶端發消息給服務端
(SYN)
- 服務端準備好進行連接
- 服務端針對客戶端的
(SYN)
給一個(ACK)
- 服務端發送一個
(SYN)
給客戶端 - 客戶端準備就緒
- 客戶端給服務端發送一個
(ACK)
其中,2和5步驟是不需要進行握手的,3和4是可以合併到一起的。所以雖然建立鏈接要6步但是隻需要三次握手,分別是1,3+4,6。
TCP的三次握手步驟
下面我們把三次握手的過程還原一下:
- 開始客戶端和服務端都處於
CLOSED
的狀態,客戶端發送SYN=1
給服務端表示要求建立鏈接,並且發送了一個seq
序號,這個時候客戶端的狀態變成SYN-SEND
。 - 服務端收到消息返回一個
ACK=1
表示確認收到,還有ack確定序號,是上一個seq
序號+1
,即x+1
,還有本次的seq
序號y
,還有一個SYN=1
建立鏈接,這個時候服務端狀態變成SYN-REVD
。 - 客戶端收到消息之後向服務端發送一個
ACK=1
表示確認收到,還有一個新的seq
序號是x+1
,還有一個ack
確定序號是上一個seq
序號+1
,即y+1
。完成之後客戶端的狀態編程ESTABLISHED
。 - 服務端接收到消息之後狀態也變成
ESTABLISHED
,鏈接通道建立。
簡要總結就是:
- 客戶端 -> SYN -> 服務端
- 客戶端 <- SYN+ACK <- 服務端
- 客戶端 -> ACK -> 服務端
思考:TCP握手爲什麼不是兩次 or 四次?
設想一下,如果只有兩次,服務端還沒有確定客戶端是否準備好了,這樣是無法穩定的進行數據傳輸的。如果四次,服務端根據客戶端的ACK
再給客戶端回覆一個ACK
,沒有什麼很大的作用還造成資源浪費,那就是很沒有必要的事情了。三次正好既可以保證可靠傳輸,也可以提高傳輸效率,
TCP的四次揮手
TCP
的揮手旨在把鏈接狀態斷開
TCP斷開鏈接的步驟
- 客戶端發消息要求斷開鏈接
(FIN)
。 - 服務端接收到請求後,會先對自己是否收到請求迴應
(ACK)
。 - 服務端處理剩餘的事情,例如服務端還有沒有發送完的消息,服務端可能還有發送出去的消息沒有得到
ACK
;也有可能服務端自己有資源要釋放等。 - 服務端處理完自己的事情,告訴客戶端可以關閉鏈接了
(FIN)
。 - 客戶端收到
FIN
,處理自己完成的事情,比如客戶端有發送給服務端沒有收到ACK
的請求等。 - 客戶端處理完成自己的事情,告訴服務端可以關閉
(ACK)
。
其中3和5是不需要進行揮手的,但是注意這裏,2和4是無法合併的。所以這裏需要四次揮手,分別是1,2,4,6。
TCP的四次揮手步驟
- 開始客戶端向服務端發送
FIN=1
要斷開鏈接,並且發送了一個seq
序號=u
,這個時候客戶端變成FIN-WAIT1
。 - 服務端接收到消息之後,返回一個
ACK=1
確定消息,還有ack
確認序號,是上一個seq
序號+1
,即u+1
,還有一個新的seq
序號爲v
,此時服務端的狀態變成CLOSE-WAIT
,客戶端收到消息之後,狀態會變成FIN-WAIT2
。 - 等服務端準備好所有的東西可以關閉鏈接的時候,向客戶端發送
ACK=1
,還要發送ack
確認序號,上一個seq
序號+1
,即u+1
,還有一個新的seq
序號爲w
,還要發送一個FIN=1
。如果有之前沒有發送完的數據,會跟着這次請求一併發送給客戶端。此時服務端的狀態變成LASE-ACK
。 - 客戶端收到消息之後,把自己這裏的東西都完成向服務端發送
ACK=1
確認消息,還發送了ack
確認序號,上一個seq
序號+1
,即w+1
,還有一個新的seq
序號爲u+1
,然後客戶端的狀態就變成了TIME-WAIT
,這種狀態會持續2WSL
,如果等待的這段時間不再收到後端的消息,2WSL
之後會變成CLOSED
。服務端接收到消息之後,狀態也變成CLOSED
。
簡要總結就是:
- 客戶端 -> FIN -> 服務端
- 客戶端 <- ACK <- 服務端
- 客戶端 <- FIN <- 服務端
- 客戶端 -> ACK -> 服務端
思考:爲什麼斷開鏈接的時候要多一個步驟2呢?
因爲斷開鏈接服務端接收到FIN
時,斷開連接要處理的問題比較多,不能直接關閉鏈接,這個時候如果不發送ACK
迴應說是內容收到了,客戶端是無法判斷這個消息服務端收到沒有,不能讓客戶端在這種情況下等太久,所以應該先回復一個ACK
報文說是收到了,你等會我這裏還有事情要處理。等到服務端的事情都處理完畢了,再發送一個FIN
,確定可以斷開鏈接了。
思考:爲什麼最後客戶端確認斷開鏈接之後還要等待2WSL呢?
- 第一用於保證客戶端發送的最後一個
ACK
報文可以到達服務器,如果這個ACK
報文丟失,服務器會覺得客戶端沒有收到我發的請求斷開報文,於是服務器就會重發一次,如果客戶端在這個2MSL
時間段內收到重傳的報文,就會重新給出迴應報文,還會重啓2MSL
計時器。 - 第二是在這個
2WSL
時間中,可以使本鏈接持續時間內產生的所有報文段從網絡中消失,這樣新的TCP
三次握手的時候就不會出現舊鏈接中失效的請求報文。
面試題:TCP爲什麼是3次握手,4次揮手?
TCP
在傳輸層,對應主機到主機的傳輸,爲應用通信提供能力,且TCP
是一個雙工協議,爲了保證雙方都建立穩定而高效的數據傳輸,使用三次握手和四次揮手的工作機制。
三次握手的步驟是:
- 客戶端向服務端發送
SYN
建立鏈接的請求(大哥,能建立鏈接嗎?)
- 服務端要將
ACK+SYN
打包爲一條消息回覆(老妹兒,我收到你的消息了,可以進行鏈接,你收到了嗎?)
- 客戶端接收到消息之後給服務端發送
ACK
作爲回覆(好嘞,走起~)
,這個時候數據傳輸通道建立。
爲什麼不是兩次,是因爲客戶端不返回ACK
,那麼服務端不知道客戶端有沒有接收到消息,如果是四次,根據ACK
再返回一次ACK
,浪費帶寬且沒有必要。
四次揮手的步驟是:
- 客戶端向服務端發送
FIN
斷開鏈接的請求(大哥,我這邊東西都發完了,斷開鏈接吧~)
- 服務端接收到信息,給客戶端發送一個
ACK
進行回覆(老妹兒?要斷開鏈接?我知道了,你稍等會兒啊)
- 服務端處理完需要處理的事情,返回
FIN
給客戶端(我這邊完事兒了,斷開鏈接吧~)
- 客戶端收到消息,處理完自己的事情,返回
ACK
給服務端(好嘞,掰掰~)
,這個時候數據傳輸通道斷開。
爲什麼這裏是四次,是因爲斷開鏈接服務端收到FIN
的時候,還有一些事情要處理,需要一些時間,這個時候不能讓客戶端等太久,所以先回復一個ACK
表示消息已經收到了,這邊有東西要處理稍微等一下。等到事情處理完,再給客戶端發送FIN同意斷開鏈接。
其實這個很好理解,在生活中,我們收到對方發送的一個文件或者一個視頻,這個時候他們需要我們根據內容進行回覆或者點評。我們應該先說一句內容收到了,我看看給你回覆,這樣不會讓對方有疑問半天沒有回覆是沒有收到還是收到了正在看。等我們看完之後再告訴對方他們要的結果。