三次握手和四次揮手(面試必問)


三次握手

當面試官問你為什么需要有三次握手、三次握手的作用、講講三次握手的時候,我想很多人會這樣回答:

      首先很多人會先講下握手的過程:

      1、第一次握手:客戶端給服務器發送一個 SYN 報文。

      2、第二次握手:服務器收到 SYN 報文之后,會應答一個 SYN+ACK 報文。

      3、第三次握手:客戶端收到 SYN+ACK 報文之后,會回應一個 ACK 報文。

      4、服務器收到 ACK 報文之后,三次握手建立完成。

      作用是為了確認雙方的接收與發送能力是否正常。

      這里我順便解釋一下為啥只有三次握手才能確認雙方的接受與發送能力是否正常,而兩次卻不可以:

          第一次握手:客戶端發送網絡包,服務端收到了。這樣服務端就能得出結論:客戶端的發送能力、服務端的接收能力是正常的。
          第二次握手:服務端發包,客戶端收到了。這樣客戶端就能得出結論:服務端的接收、發送能力,客戶端的接收、發送能力是正常的。不過此時服務器並不能確認客戶端的接收能力是否正常。
          第三次握手:客戶端發包,服務端收到了。這樣服務端就能得出結論:客戶端的接收、發送能力正常,服務器自己的發送、接收能力也正常。

      因此,需要三次握手才能確認雙方的接收與發送能力是否正常。

      這樣回答其實也是可以的,但我覺得,這個過程的我們應該要描述的更詳細一點,因為三次握手的過程中,雙方是由很多狀態的改變的,而這些狀態,也是面試官可能會問的點。所以我覺得在回答三次握手的時候,我們應該要描述的詳細一點,而且描述的詳細一點意味着可以扯久一點。加分的描述我覺得應該是這樣:

      剛開始客戶端處於 closed 的狀態,服務端處於 listen 狀態。然后
      1、第一次握手:客戶端給服務端發一個 SYN 報文,並指明客戶端的初始化序列號 ISN(c)。此時客戶端處於 SYN_Send 狀態。

      2、第二次握手:服務器收到客戶端的 SYN 報文之后,會以自己的 SYN 報文作為應答,並且也是指定了自己的初始化序列號 ISN(s),同時會把客戶端的 ISN + 1 作為 ACK 的值,表示自己已經收到了客戶端的 SYN,此時服務器處於 SYN_REVD 的狀態。

      3、第三次握手:客戶端收到 SYN 報文之后,會發送一個 ACK 報文,當然,也是一樣把服務器的 ISN + 1 作為 ACK 的值,表示已經收到了服務端的 SYN 報文,此時客戶端處於 establised 狀態。

      4、服務器收到 ACK 報文之后,也處於 establised 狀態,此時,雙方以建立起了鏈接。

 

 

 Ps:(1)SYN=1 表示該報文不攜帶數據,但消耗一個序號 seq=x,seq=x是客戶端的初始化序列號,因為tcp是面向字節流的
     (2)SYN=1 表示該報文不攜帶數據,但消耗一個序號 seq=y,seq=y是服務器的初始化序列號,ACK=1是一個確認號
    ack=x+1,表示服務器下次接收到的序號希望是x+1。然后服務器進入到SYN-RCVD等待的狀態
     (3)ACK=1是一個確認號,seq=x+1是上一次服務器回應的序號要求,ack=y+1表示客戶下一次接收到的序號希望是y+1

三次握手的作用

      三次握手的作用也是有好多的,多記住幾個,保證不虧。例如:
      1、確認雙方的接受能力、發送能力是否正常。
      2、指定自己的初始化序列號,為后面的可靠傳送做准備。
      3、如果是 https 協議的話,三次握手這個過程,還會進行數字證書的驗證以及加密密鑰的生成到。

      單單這樣還不足以應付三次握手,面試官可能還會問一些其他的問題,例如:
1、(ISN)是固定的嗎?

      三次握手的一個重要功能是客戶端和服務端交換ISN(Initial Sequence Number), 以便讓對方知道接下來接收數據的時候如何按序列號組裝數據。

      如果ISN是固定的,攻擊者很容易猜出后續的確認號,因此 ISN 是動態生成的。
2、什么是半連接隊列

      服務器第一次收到客戶端的 SYN 之后,就會處於 SYN_RCVD 狀態,此時雙方還沒有完全建立其連接,服務器會把此種狀態下請求連接放在一個隊列里,我們把這種隊列稱之為半連接隊列。當然還有一個全連接隊列,就是已經完成三次握手,建立起連接的就會放在全連接隊列中。如果隊列滿了就有可能會出現丟包現象。

          這里在補充一點關於SYN-ACK 重傳次數的問題: 服務器發送完SYN-ACK包,如果未收到客戶確認包,服務器進行首次重傳,等待一段時間仍未收到客戶確認包,進行第二次重傳,如果重傳次數超 過系統規定的最大重傳次數,系統將該連接信息從半連接隊列中刪除。注意,每次重傳等待的時間不一定相同,一般會是指數增長,例如間隔時間為 1s, 2s, 4s, 8s, …

3、三次握手過程中可以攜帶數據嗎

      很多人可能會認為三次握手都不能攜帶數據,其實第三次握手的時候,是可以攜帶數據的。也就是說,第一次、第二次握手不可以攜帶數據,而第三次握手是可以攜帶數據的。

為什么這樣呢?大家可以想一個問題,假如第一次握手可以攜帶數據的話,如果有人要惡意攻擊服務器,那他每次都在第一次握手中的 SYN 報文中放入大量的數據,因為攻擊者根本就不理服務器的接收、發送能力是否正常,然后瘋狂着重復發 SYN 報文的話,這會讓服務器花費很多時間、內存空間來接收這些報文。也就是說,第一次握手可以放數據的話,其中一個簡單的原因就是會讓服務器更加容易受到攻擊了。
而對於第三次的話,此時客戶端已經處於 established 狀態,也就是說,對於客戶端來說,他已經建立起連接了,並且也已經知道服務器的接收、發送能力是正常的了,所以能攜帶數據頁沒啥毛病。

為什么要進行三次握手?

 

 

當進行第一次握手,網絡不好可能會堵塞,所以連接的請求並沒有到達服務器端;
但是tcp連接有超時重傳的機制,所以再一次發送請求,這時候服務器端接收到了你的請求,他也會返回一個請求給你,這是第二次握手;
但是這時候網絡環境突然又好了起來,那個堵塞的請求到達了服務器端,服務器端又給你回了一個請求,但是你又不想給服務器發送請求,這時候服務器的資源會進行占用等待你的請求,為了不使服務器的資源繼續占用,你又必須發送一個請求給服務器;
所以要進行3次握手

四次揮手


1、第一次揮手:客戶端發送一個 FIN 報文,報文中會指定一個序列號。此時客戶端處於FIN_WAIT1狀態。

2、第二次握手:服務端收到 FIN 之后,會發送 ACK 報文,且把客戶端的序列號值 + 1 作為 ACK 報文的序列號值,表明已經收到客戶端的報文了,此時服務端處於 CLOSE_WAIT狀態。

3、第三次揮手:如果服務端也想斷開連接了,和客戶端的第一次揮手一樣,發給 FIN 報文,且指定一個序列號。此時服務端處於 LAST_ACK 的狀態。

4、第四次揮手:客戶端收到 FIN 之后,一樣發送一個 ACK 報文作為應答,且把服務端的序列號值 + 1 作為自己 ACK 報文的序列號值,此時客戶端處於 TIME_WAIT 狀態。需要過一陣子以確保服務端收到自己的 ACK 報文之后才會進入 CLOSED 狀態

5、服務端收到 ACK 報文之后,就處於關閉連接了,處於 CLOSED 狀態。

 

 

 

這里特別需要主要的就是TIME_WAIT這個狀態了,這個是面試的高頻考點,就是要理解,為什么客戶端發送 ACK 之后不直接關閉,而是要等一陣子才關閉。這其中的原因就是,要確保服務器是否已經收到了我們的 ACK 報文,如果沒有收到的話,服務器會重新發 FIN 報文給客戶端,客戶端再次收到 ACK 報文之后,就知道之前的 ACK 報文丟失了,然后再次發送 ACK 報文。
至於 TIME_WAIT 持續的時間至少是一個報文的來回時間。一般會設置一個計時,如果過了這個計時沒有再次收到 FIN 報文,則代表對方成功就是 ACK 報文,此時處於 CLOSED 狀態。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM