在面試中,三次握手和四次揮手能夠說是問的最頻繁的一個知識點了,我相信你們也都看過不少關於三次握手與四次揮手的文章。面試
今天的這篇文章,重點是圍繞着面試,咱們應該掌握哪些比較重要的點,哪些是比較多被面試官給問到的,我以爲若是你能把我下面列舉的一些點都記住、理解,我想就差很少了。服務器
三次握手網絡
當面試官問你爲何須要有三次握手、三次握手的做用、講講三次握手的時候,我想不少人會這樣回答。加密
首先不少人會先講下握手的過程:3d
做用是爲了確認雙方的接收與發送能力是否正常。blog
這裏我順便解釋一下爲啥只有三次握手才能確認雙方的接受與發送能力是否正常,而兩次卻不能夠:隊列
這樣服務端就能得出結論:客戶端的發送能力、服務端的接收能力是正常的。內存
這樣客戶端就能得出結論:服務端的接收、發送能力,客戶端的接收、發送能力是正常的。不過此時服務器並不能確認客戶端的接收能力是否正常。it
這樣服務端就能得出結論:客戶端的接收、發送能力正常,服務器本身的發送、接收能力也正常。sed
所以,須要三次握手才能確認雙方的接收與發送能力是否正常。
這樣回答其實也是能夠的,但我以爲,這個過程咱們應該要描述的更詳細一點,由於三次握手的過程當中,雙方是由不少狀態的改變的,而這些狀態,也是面試官可能會問的點。
因此我以爲在回答三次握手的時候,咱們應該要描述的詳細一點,並且描述的詳細一點意味着能夠扯久一點。
加分的描述我以爲應該是這樣:剛開始客戶端處於 Closed 的狀態,服務端處於 Listen 狀態。
而後:
第一次握手:客戶端給服務端發一個 SYN 報文,並指明客戶端的初始化序列號 ISN(c)。此時客戶端處於 SYN_Send 狀態。
第二次握手:服務器收到客戶端的 SYN 報文以後,會以本身的 SYN 報文做爲應答,而且也是指定了本身的初始化序列號 ISN(s)。
同時會把客戶端的 ISN + 1 做爲 ACK 的值,表示本身已經收到了客戶端的 SYN,此時服務器處於 SYN_REVD 的狀態。
第三次握手:客戶端收到 SYN 報文以後,會發送一個 ACK 報文,固然,也是同樣把服務器的 ISN + 1 做爲 ACK 的值,表示已經收到了服務端的 SYN 報文,此時客戶端處於 establised 狀態。
服務器收到 ACK 報文以後,也處於 establised 狀態,此時,雙方已創建起了連接。
三次握手的做用
三次握手的做用也是有好多的,多記住幾個,保證不虧。例如:
單單這樣還不足以應付三次握手,面試官可能還會問一些其餘的問題,例如:
①(ISN)是固定的嗎
三次握手的一個重要功能是客戶端和服務端交換 ISN(Initial Sequence Number),以便讓對方知道接下來接收數據的時候如何按序列號組裝數據。
若是 ISN 是固定的,攻擊者很容易猜出後續的確認號,所以 ISN 是動態生成的。
②什麼是半鏈接隊列
服務器第一次收到客戶端的 SYN 以後,就會處於 SYN_RCVD 狀態,此時雙方尚未徹底創建其鏈接,服務器會把此種狀態下請求鏈接放在一個隊列裏,咱們把這種隊列稱之爲半鏈接隊列。
固然還有一個全鏈接隊列,就是已經完成三次握手,創建起鏈接的就會放在全鏈接隊列中。若是隊列滿了就有可能會出現丟包現象。
這裏在補充一點關於SYN-ACK 重傳次數的問題:
注意,每次重傳等待的時間不必定相同,通常會是指數增加,例如間隔時間爲 1s,2s,4s,8s......
③三次握手過程當中能夠攜帶數據嗎
不少人可能會認爲三次握手都不能攜帶數據,其實第三次握手的時候,是能夠攜帶數據的。
也就是說,第一次、第二次握手不能夠攜帶數據,而第三次握手是能夠攜帶數據的。
爲何這樣呢?你們能夠想一個問題,假如第一次握手能夠攜帶數據的話,若是有人要惡意攻擊服務器,那他每次都在第一次握手中的 SYN 報文中放入大量的數據。
由於攻擊者根本就不理服務器的接收、發送能力是否正常,而後瘋狂着重複發 SYN 報文的話,這會讓服務器花費不少時間、內存空間來接收這些報文。
也就是說,第一次握手能夠放數據的話,其中一個簡單的緣由就是會讓服務器更加容易受到攻擊了。
而對於第三次的話,此時客戶端已經處於 established 狀態,也就是說,對於客戶端來講,他已經創建起鏈接了,而且也已經知道服務器的接收、發送能力是正常的了,因此能攜帶數據頁沒啥毛病。
關於三次握手的,HTTPS 的認證過程能知道一下更好,不過我就不說了,留着寫 HTTP 面試相關時的文章再說。
四次揮手
四次揮手也同樣,千萬不要對方一個 FIN 報文,我方一個 ACK 報文,再我方一個 FIN 報文,對方一個 ACK 報文。
而後結束,要說的詳細一點,例如像下面這樣就差很少了,要把每一個階段的狀態記好,我上次面試就被問了幾個了,呵呵。我答錯了,還覺得本身答對了,當時還解釋的頭頭是道,呵呵。
剛開始雙方都處於 establised 狀態,假如是客戶端先發起關閉請求,則:
第一次揮手:客戶端發送一個 FIN 報文,報文中會指定一個序列號。此時客戶端處於 FIN_WAIT1 狀態。
第二次握手:服務端收到 FIN 以後,會發送 ACK 報文,且把客戶端的序列號值 +1 做爲 ACK 報文的序列號值,代表已經收到客戶端的報文了,此時服務端處於 CLOSE_WAIT 狀態。
第三次揮手:若是服務端也想斷開鏈接了,和客戶端的第一次揮手同樣,發給 FIN 報文,且指定一個序列號。此時服務端處於 LAST_ACK 的狀態。
第四次揮手:客戶端收到 FIN 以後,同樣發送一個 ACK 報文做爲應答,且把服務端的序列號值 +1 做爲本身 ACK 報文的序列號值,此時客戶端處於 TIME_WAIT 狀態。
須要過一陣子以確保服務端收到本身的 ACK 報文以後纔會進入 CLOSED 狀態
這裏特別須要注意的就是 TIME_WAIT 這個狀態了,這個是面試的高頻考點,就是要理解,爲何客戶端發送 ACK 以後不直接關閉,而是要等一陣子才關閉。
這其中的緣由就是,要確保服務器是否已經收到了咱們的 ACK 報文,若是沒有收到的話,服務器會從新發 FIN 報文給客戶端,客戶端再次收到 ACK 報文以後,就知道以前的 ACK 報文丟失了,而後再次發送 ACK 報文。
至於 TIME_WAIT 持續的時間至少是一個報文的來回時間。通常會設置一個計時,若是過了這個計時沒有再次收到 FIN 報文,則表明對方成功,就是 ACK 報文,此時處於 CLOSED 狀態。
這裏我給出每一個狀態所包含的含義,有興趣的能夠看看:
最後,再放下三次握手與四次揮手的圖: