TCP三次握手四次揮手

所謂三次握手(Three-Way Handshake)即建立TCP連接,就是指建立一個TCP連接時,需要客戶端和服務端總共發送3個包以確認連接的建立。在socket編程中,這一過程由客戶端執行connect來觸發。
TCP三次握手
(1)第一次握手:Client將標誌位SYN置爲1,隨機產生一個值seq=J,並將該數據包發送給Server,Client進入SYN_SENT狀態,等待Server確認。
(2)第二次握手:Server收到數據包後由標誌位SYN=1知道Client請求建立連接,Server將標誌位SYN和ACK都置爲1,ack=J+1,隨機產生一個值seq=K,並將該數據包發送給Client以確認連接請求,Server進入SYN_RCVD狀態。
(3)第三次握手:Client收到確認後,檢查ack是否爲J+1,ACK是否爲1,如果正確則將標誌位ACK置爲1,ack=K+1,並將該數據包發送給Server,Server檢查ack是否爲K+1,ACK是否爲1,如果正確則連接建立成功,Client和Server進入ESTABLISHED狀態,完成三次握手,隨後Client與Server之間可以開始傳輸數據了。
        
SYN攻擊:
在三次握手過程中,Server發送SYN-ACK之後,收到Client的ACK之前的TCP連接稱爲半連接(half-open connect),此時Server處於SYN_RCVD狀態,當收到ACK後,Server轉入ESTABLISHED狀態。SYN攻擊就是Client在短時間內僞造大量不存在的IP地址,並向Server不斷地發送SYN包,Server回覆確認包,並等待Client的確認,由於源地址是不存在的,因此,Server需要不斷重發直至超時,這些僞造的SYN包將產時間佔用未連接隊列,導致正常的SYN請求因爲隊列滿而被丟棄,從而引起網絡堵塞甚至系統癱瘓。SYN攻擊時一種典型的DDOS攻擊,檢測SYN攻擊的方式非常簡單,即當Server上有大量半連接狀態且源IP地址是隨機的,則可以斷定遭到SYN攻擊了,使用如下命令可以讓之現行:
                #netstat -nap | grep SYN_RECV
爲什麼要有第三次握手?
相信前兩次握手大家都很好理解,一次是客戶端向服務端發出連接請求,此時只能是客戶端向服務端發送數據,而服務端不能向客戶端發送數據;第二次是服務端向客戶端發送的連接請求,這次過後雙方都可以發送數據了;那其實兩次連接就能解決問題的,爲什麼還要第三次呢? 
其實,第三次的握手是爲了防止已經失效的連接請求報文段突然又傳送到了服務端,從而產生錯誤。這個已經失效的連接報文段是怎麼來的? 因爲客戶端在發送了SYN數據報後可能又這種情況,因爲當時網絡擁塞,所以過了超時重傳的等待時間後客戶端沒有收到服務端的確認,所以它又發送了第二次SYN報文段,此時服務端發送過來了SYN應答報文段。但是可能過了一會,剛剛處於擁塞環境的SYN報文段又到達了服務端,這時服務端會認爲客戶端想和自己建立第二次連接,於是又向客戶端發送了SYN應答報文段,而此時客戶端可能已經完成了數據傳送並釋放了和服務端的連接,它的狀態會變爲CLOSED,從而導致永遠無法收到服務端發來的SYN報文段,從而使服務端一直再等待客戶端發來數據,這樣會浪費許多服務端的資源。 
所以,就引入了第三次握手,例如上面的情況,客戶端在收到應答報文段後不會想服務端再次發送確認,所以服務端也就無法建立連接。
所謂四次揮手(Four-Way Wavehand)即終止TCP連接,就是指斷開一個TCP連接時,需要客戶端和服務端總共發送4個包以確認連接的斷開。在socket編程中,這一過程由客戶端或服務端任一方執行close來觸發。


TCP四次揮手
由於TCP連接時全雙工的,因此,每個方向都必須要單獨進行關閉,這一原則是當一方完成數據發送任務後,發送一個FIN來終止這一方向的連接,收到一個FIN只是意味着這一方向上沒有數據流動了,即不會再收到數據了,但是在這個TCP連接上仍然能夠發送數據,直到這一方向也發送了FIN。首先進行關閉的一方將執行主動關閉,而另一方則執行被動關閉,上圖描述的即是如此。
(1)第一次揮手:Client發送一個FIN,用來關閉Client到Server的數據傳送,Client進入FIN_WAIT_1狀態。
(2)第二次揮手:Server收到FIN後,發送一個ACK給Client,確認序號爲收到序號+1(與SYN相同,一個FIN佔用一個序號),Server進入CLOSE_WAIT狀態。
(3)第三次揮手:Server發送一個FIN,用來關閉Server到Client的數據傳送,Server進入LAST_ACK狀態。
(4)第四次揮手:Client收到FIN後,Client進入TIME_WAIT狀態,接着發送一個ACK給Server,確認序號爲收到序號+1,Server進入CLOSED狀態,完成四次揮手。

爲什麼要有四次揮手相比於爲什麼要有三次握手應該不難理解,四次揮手分別是各自互相發送FIN報文,以及發送對對方FIN報文的確認報文,值得一提的是爲什麼在最後一次揮手後要等待2*MSL的時間? 
這樣做是爲了保證A的最後一次揮手(ACK報文段)能夠到達B。出了LAST-ACK狀態的B如果收不到A的ACK字段,那麼他會在重傳一次FIN+ACK字段,A收到後會重傳一次確認,重新啓動時間等待計時器(2*MSL),如果A不等待2MSL,如果最後一次確認沒有傳到B, 那麼B的重傳A就再也收不到了,那麼B就會一直重傳,並永遠無法釋放連接。

--------------------- 
作者:北辰北 
來源:CSDN 
原文:https://blog.csdn.net/CC_clear/article/details/75331780 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

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