有趣的三次握手和四次揮手問題

說到計算機網絡,那就必須要提到TCP協議,談到TCP協議,那就要提一提TCP協議裏最有名的“三次握手和四次揮手”,對於這個知識點大家肯定或多或少在大學課程裏,在面試中被問到過,所以我就想專門寫一篇博客來好好地學習和記錄一下我從中所學到的知識。
首先要清晰透徹的學習這個知識點之前我們要對TCP報文有所瞭解,因爲會用到很多TCP豹紋的知識點,所以加入你不熟悉的話,可以移步到:點擊這裏查看TCP報文知識點
假如你已經對TCP報文有所瞭解,那麼我們可以開始對三次握手和四次揮手的學習了。

三次握手:

三次握手的本質是什麼呢,其實就是兩個服務器之間的TCP通信的建立過程。
下首先看一張圖:
三次握手
這是一張三次握手的過程圖,首先我們可以看出左邊的是client,也就是客戶機,右邊的是server,也就是服務器,圖上別的都是一堆奇怪的英文,但是有些我們感到很熟悉,沒關係,下面我會詳細講一講整個過程是如何的:
(1)第一步:客戶機發送請求連接報文
首先我們能看到客戶機向服務器發送了一條報文,SYN=1,seq=J,SYN大家一定都知道,當它等於1時說明這條報文時連接請求或者連接接受報文,這條報文明顯是一條連接請求報文,seq大家也知道是序號,客戶機隨機生成了一個序號等於J,然後將這整個報文傳給了服務器,服務器一看到這條報文就明白了客戶機向其請求建立TCP連接,這時候客戶機是SYN_Client狀態,是一個發送狀態。服務器接收後變爲SYN_RCVD狀態,也就是連接接受狀態。
(2)第二步:服務器回覆並同意連接
我們知道服務器知道客戶機想要連接,那麼它要給客戶機“回一封信”,告訴客戶機以下兩點:
1.你的請求我收到了
2.同意連接
所以便有了第二步
我們來看一下這一步所傳遞的參數:
SYN=1表示這個報文是一個連接請求報文或者連接接受報文,ACK=1表明連接建立,ack=J+1表明這個報文是第一步報文的下一條內容回覆,seq則是服務器隨機產生的一個序號
(2)第三步:客戶端回覆並同意連接
第三次握手是客戶機對服務器的一次回覆,一共兩個參數,ACK=1表明連接建立,ack=K+1表示其是第二次握手中的報文的回覆。至此,三次握手全部完成,連接建立。

這裏我想提幾個有趣的點給大家分享:
(1)爲何不是兩次握手?
大家可能會發現假如沒有第三次握手好像也是行得通的,真的是這樣麼?
大家想一下以下兩個場景:
1.客戶端發送了一個連接,但是由於網絡阻塞,導致這個請求延遲了很久,過期了,客戶端此時新發送了一個請求,但是剛好這時候老的請求先到達了,服務器收到後立刻回覆了客戶端一條同意連接的報文,假如是兩次握手,此時連接已經建立了,這明顯是不對的,三次握手情況下,客戶端收到回信後根據ack號來判斷髮現這個連接是一個已經過期的連接,所以它會回覆一條RST=1的報文,表示我們要終止這次連接,這就是一種很完善的機制,可以有效避免過期的連接佔用資源。
2.又是網絡阻塞問題,導致客戶端發出的報文遲遲沒有回覆,這時候客戶端就會不斷地發送報文請求連接,假如是兩次握手機制,剛纔那些報文過一會兒到了服務器,服務器便發送大量連接成功報文給客戶端,這時候建立了大量無效連接,極大地浪費了服務器資源,但是三次握手情況下,客戶端回覆時會將回復無效連接的報文中表示不建立連接,這便可以節省大量服務器資源。

(2)根據三次握手產生的SYN攻擊
這個可能大家很感興趣,這是一個關於網絡攻擊的知識點,具體原理是客戶端僞造大量不存在的IP地址向服務器發送連接請求,這時候服務器收到請求後進行回覆,但是由於IP地址是不存在的,所以造成服務器收不到回覆,便會不斷重新發送回復請求,這時由於所有的重發都佔用了未連接隊列,導致正確的SYN請求由於隊列滿了而被丟棄,從而引起網絡堵塞導致網絡癱瘓,SYN攻擊是一種典型的DDOS攻擊,檢測方式是查看服務器是不是有大量半連接狀態且IP地址隨機,具體命令如下:
#netstat -nap | grep SYN_RECV
解決SYN攻擊的思路是對Linux 內核的參數(半連接隊列大小)做設置,當網卡接受請求數大於內核能夠處理數量時,做出處理,如直接回復RST。

四次揮手:

四次揮手的過程如下圖所示:
四次揮手過程
四次揮手實際上就是TCP連接斷開的過程。
整個過程分爲以下四步:
(1)第一步:客戶端發起斷開連接請求
客戶端發送一個數據包此時FIN=1,並且seq=M
(2)第二步:服務器回覆客戶端請求
服務端收到第一步的請求後,發送一個ack=M+1的確認包,表示已經收到請求,此時服務器進入到CLOSE_WAIT狀態,表示關閉等待。
(3)第三步:服務器發送FIN包,關閉server到clinet的數據傳送
服務器發送一個FIN=1的包,並且seq=N ,並且服務器發送後變爲LAST_ACK狀態,意味最後確認
(4)第四步:客戶端發送回覆確認包,服務器收到後關閉
客戶端發送確認包ACK=1表明連接還在持續,ack=N+1(圖中錯誤)

關於四次揮手,有地下幾個問題需要注意:
1.爲什麼是四次揮手而不是三次揮手?
這個問題其實是因爲服務端在進行第二次握手和第三次握手時,第二次握手回覆給客戶端後可能還有餘下的報文或者數據沒有傳送完畢,在這些數據和報文都傳送完畢後,纔會發送FIN包,來表示服務端的數局全部傳送完畢,可以關閉連接了,等待最後一次確認後,服務器就關閉了。

2.客戶端在完成第四次握手後會有一個 TIME_WAIT 等待的時間是 2MSL,在此結束後會close,請問爲什麼?
這個是因爲由於網絡延遲或者別的問題發生時可能有一些數據包沒有傳送到客戶端或者延遲傳送到客戶端,MSL是報文最大生存時間,2MSL 的時間是從客戶端接收到 FIN 後發送 ACK 開始計時的。如果在 TIME-WAIT 時間內,因爲客戶端的 ACK 沒有傳輸到服務端,客戶端又接收到了服務端重發的 FIN 報文,那麼 2MSL 時間將重新計時。說白了就是客戶端的第四次握手傳送出去後假如丟失了,服務器沒收到將會重新發送FIN報文,也就是第三次握手的報文,這兩個過程加起來最多是2MSL 的時間。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章