TCP三次握手和四次揮手分析

對於socket開發者來說,主要是使用API進行編程,TCP從建立連接到數據收發再到斷開這整個過程可以通過幾個簡單的socket接口進行實現,TCP創建過程和鏈接折除過程是由TCP/IP協議棧自動創建的.因此開發者並不需要控制這個過程.但是對於理解TCP底層運作機制,相當有幫助.下面的內容主要根據自己對TCP協議的三次握手做下總結:

TCP的三次握手:

三次握手指的是建立TCP連接,客戶端和服務端共發送三個包,目的是連接指定服務器及端口,並且同步雙方的序列號和確認號以及交換TCP窗口大小信息。

                         

第一次握手:

客戶端發送一個TCP的SYN標誌位置1的包指明客戶打算連接的服務器的端口,以及初始序號X,保存在包頭的序列號(Sequence Number)字段裏。

 

                                   

第二次握手:

服務器發回確認包(ACK)應答。即SYN標誌位和ACK標誌位均爲1同時,將確認序號(Acknowledgement Number)設置爲客戶的I S N加1以.即X+1。

                                     

 

第三次握手.

客戶端再次發送確認包(ACK) SYN標誌位爲0,ACK標誌位爲1.並且把服務器發來ACK的序號字段+1,放在確定字段中發送給對方.並且在數據段放寫ISN的+1

                                      

從三次握手看優缺點:

優點:爲什麼需要三次握手,而不是兩次握手?

1.從上面的示意圖可以看出,3次握手完成兩個重要的功能,既要雙方做好發送數據的準備工作(雙方都知道彼此已準備好),也要允許雙方就初始序列號進行協商,這個序列號在握手過程中被髮送和確認,現在把三次握手改成僅需要兩次握手,死鎖是可能發生的。作爲例子,考慮計算機S和C之間的通信,假定C給S發送一個連接請求分組,S收到了這個分組,併發 送了確認應答分組。按照兩次握手的協定,S認爲連接已經成功地建立了,可以開始發送數據分組。可是,C在S的應答分組在傳輸中被丟失的情況下,將不知道S 是否已準備好,不知道S建立什麼樣的序列號,C甚至懷疑S是否收到自己的連接請求分組。在這種情況下,C認爲連接還未建立成功,將忽略S發來的任何數據分 組,只等待連接確認應答分組。而S在發出的分組超時後,重複發送同樣的分組。這樣就形成了死鎖。

2. 三次握手發送方再次發送確認的必要性

主 要是爲了防止已失效的連接請求報文段突然又傳到了B,因而產生錯誤。假定出現一種異常情況,即A發出的第一個連接請求報文段並沒有丟失,而是在某些網絡結 點長時間滯留了,一直延遲到連接釋放以後的某個時間纔到達B,本來這是一個早已失效的報文段。但B收到此失效的連接請求報文段後,就誤認爲是A又發出一次 新的連接請求,於是就向A發出確認報文段,同意建立連接。假定不採用三次握手,那麼只要B發出確認,新的連接就建立了,這樣一直等待A發來數據,B的許多 資源就這樣白白浪費了。

 

缺點:容易受到SYN攻擊

在三次握手過程中,服務器發送SYN-ACK之後,收到客戶端的ACK之前的TCP連接稱爲半連接(half-open connect).此時服務器處於SYN_RECV狀態.當收到ACK後,服務器轉入ESTABLISHED狀態,這種情況下是客戶端和服務端正常建立連接通信的時候,但是Syn攻擊就是 攻擊客戶端 在短時間內僞造大量不存在的IP地址,向服務器不斷地發送syn包,服務器回覆確認包,並等待客戶的確認,由於源地址是不存在的,服務器需要不斷的重發直 至超時,這些僞造的SYN包將長時間佔用未連接隊列,正常的SYN請求被丟棄,目標系統運行緩慢,嚴重者引起網絡堵塞甚至系統癱瘓。

實例:典型的DDOS攻擊就是一種SYN攻擊,但是檢測SYN攻擊非常的方便,當你在服務器上看到大量的半連接狀態時,特別是源IP地址是隨機的,基本上可以斷定這是一次SYN攻擊.在Linux下可以如下命令檢測是否被Syn攻擊

netstat -n -p TCP | grep SYN_RECV

一般較新的TCP/IP協議棧都對這一過程進行修正來防範Syn攻擊,修改tcp協議實現。主要方法有SynAttackProtect保護機制、SYN cookies技術、增加最大半連接和縮短超時時間等,但是不能完全防範syn攻擊。

下面進行觀察一組三次握手的抓包情況

 

TCP的四次揮手:

TCP的連接的拆除需要發送四個包,因此稱爲四次揮手(four-way handshake)。客戶端或服務器均可主動發起揮手動作,在socket編程中,任何一方執行close()操作即可產生揮手操作。

                    

 

1.爲什麼建立連接協議是三次握手,而關閉連接卻是四次握手呢?

這是因爲服務端的LISTEN狀態下的SOCKET當收到SYN報文的連接請求後,它可以把ACK和SYN(ACK起應答作用,而SYN起同步作用)放在一個報文裏來發送。但關閉連接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數據發送給你了;但未必你所有的數據都全部發送給對方了,所以你可能未必會馬上會關閉SOCKET,也即你可能還需要發送一些數據給對方之後,再發送FIN報文給對方來表示你同意現在可以關閉連接了,所以它這裏的ACK報文和FIN報文多數情況下都是分開發送的。

從socket編程的角度來看有一下幾點

a. 默認情況下(不改變socket選項),當你調用close( or closesocket,以下說close不再重複)時,如果發送緩衝中還有數據,TCP會繼續把數據發送完。

b. 發送了FIN只是表示這端不能繼續發送數據(應用層不能再調用send發送),但是還可以接收數據。

c. 應用層如何知道對端關閉?通常,在最簡單的阻塞模型中,當你調用recv時,如果返回0,則表示對端關閉。在這個時候通常的做法就是也調用close,那麼TCP層就發送FIN,繼續完成四次握手。如果你不調用close,那麼對端就會處於FIN_WAIT_2狀態,而本端則會處於CLOSE_WAIT狀態

d. 在很多時候,TCP連接的斷開都會由TCP層自動進行,例如你CTRL+C終止你的程序,TCP連接依然會正常關閉

2. 爲什麼TIME_WAIT狀態還需要等2MSL後才能返回到CLOSED狀態?

可靠的實現TCP全雙工鏈接的終止:

雖然雙方都同意關閉連接了,而且握手的4個報文也都協調和發送完畢,按理可以直接回到CLOSED狀態(就好比從SYN_SEND狀態到ESTABLISH狀態那樣);但是因爲我們必須要假想網絡是不可靠的,你無法保證你最後發送的ACK報文會一定被對方收到,因此對方處於LAST_ACK狀態下的SOCKET可能會因爲超時未收到ACK報文,而重發FIN報文,所以這個TIME_WAIT狀態的作用就是用來重發可能丟失的ACK報文

下面抓取的是四次揮手的報文

 

以上的總結關於三次握手及四次揮手的過程以及三次握手的優缺點和四次揮手的特點,謝謝閱讀,有什麼不正確的地方歡迎評論區點評指正。

 

 

 

 

 

 

 

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