咱們都知道 TCP 是 可靠的數據傳輸協議,UDP是不可靠傳輸,那麼TCP它是怎麼保證可靠傳輸的呢?那咱們就不得不提 TCP 的三次握手和四次揮手。服務器
下圖爲創建鏈接三次握手的流程圖網絡
下面經過咱們 wireshark 抓包工具來分析三次握手併發
三次握手數據包tcp
創建鏈接。客戶端發送鏈接請求報文段,將SYN位置爲1,Sequence Number爲x;(x 是隨機生成的一個 int 數值)而後,客戶端進入SYN_SEND狀態,等待服務器的確認;工具
服務器收到SYN報文段。服務器收到客戶端的SYN報文段,須要對這個SYN報文段進行確認,設置Acknowledgment Number爲x+1(Sequence Number+1);同時,本身本身還要發送SYN請求信息,將SYN位置爲1,Sequence Number爲 y (y 是隨機生存的一個 int 數值);服務器端將上述全部信息放到一個報文段(即SYN+ACK報文段)中,一併發送給客戶端,此時服務器進入SYN_RECV狀態;spa
客戶端收到服務器的SYN+ACK報文段。而後將Acknowledgment Number設置爲y+1,向服務器發送ACK報文段,這個報文段發送完畢之後,客戶端和服務器端都進入ESTABLISHED狀態,完成TCP三次握手。計算機網絡
Client (可使客戶端,也能夠是服務器端),設置Sequence Number和Acknowledgment Number,向 Server發送一個FIN報文段;此時,Client 進入FIN_WAIT_1狀態;這表示 Client 沒有數據要發送給 Server了;3d
客戶端發送第一次揮手後,就不能在向 服務端發送數據了。server
Server 收到了 Client 發送的FIN報文段,向 Client 回一個ACK報文段,Acknowledgment Number 爲 Sequence Number 加 1;Client 進入 FIN_WAIT_2 狀態;Server 告訴 Client ,我「贊成」你的關閉請求;blog
Server 第一次響應後,還能夠繼續向 Client 發送數據,這裏只是告訴 Client ,我收到你發送的關閉請求。
Server 向 Client 發送 FIN 報文段,請求關閉鏈接,同時 Server 進入 CLOSE_WAIT 狀態;
當 Server 的數據響應完成後,再告訴 Client,我這邊也能夠關閉請求了, 這時
Server 就不能再向 Client 發送數據了
Client 收到 Server 發送的 FIN 報文段,向 Server 發送 ACK 報文段,而後 Client 進入
TIME_WAIT 狀態;Server 收到 Client 的 ACK 報文段之後,就關閉鏈接;此時,Client
等待2MSL後依然沒有收到回覆,則證實 Server 端已正常關閉,那好,Client 也能夠關閉鏈接了。
MSL是Maximum Segment Lifetime英文的縮寫,中文能夠譯爲「報文最大生存時間」,他是任何報文在網絡上存在的最長時間,超過這個時間報文將被丟棄。由於tcp報文(segment)是ip數據報(datagram)的數據部分,具體稱謂請參見《數據在網絡各層中的稱呼》一文,而ip頭中有一個TTL域,TTL是time to live的縮寫,中文能夠譯爲「生存時間」,這個生存時間是由源主機設置初始值但不是存的具體時間,而是存儲了一個ip數據報能夠通過的最大路由數,每通過一個處理他的路由器此值就減1,當此值爲0則數據報將被丟棄,同時發送ICMP報文通知源主機。RFC 793中規定MSL爲2分鐘,實際應用中經常使用的是30秒,1分鐘和2分鐘等。
2MSL即兩倍的MSL,TCP的TIME_WAIT狀態也稱爲2MSL等待狀態,當TCP的一端發起主動關閉,在發出最後一個ACK包後,即第3次握手完成後發送了第四次握手的ACK包後就進入了TIME_WAIT狀態,必須在此狀態上停留兩倍的MSL時間,等待2MSL時間主要目的是怕最後一個ACK包對方沒收到,那麼對方在超時後將重發第三次握手的FIN包,主動關閉端接到重發的FIN包後能夠再發一個ACK應答包。在TIME_WAIT狀態時兩端的端口不能使用,要等到2MSL時間結束纔可繼續使用。當鏈接處於2MSL等待階段時任何遲到的報文段都將被丟棄。不過在實際應用中能夠經過設置SO_REUSEADDR選項達到沒必要等待2MSL時間結束再使用此端口。
TTL與MSL是有關係的但不是簡單的相等的關係,MSL要大於等於TTL。
爲何要三次握手
TCP 創建鏈接,其實經過兩次握手就能夠創建鏈接了,爲何要三次呢?是否是畫蛇添足呢?
一、《計算機網絡》中是這樣說的:
爲了防止已失效的鏈接請求報文段忽然又傳送到了服務端,於是產生錯誤。
在書中同時舉了一個例子,以下:
已失效的鏈接請求報文段」的產生在這樣一種狀況下:client發出的第一個鏈接請求報文段並無丟失,而是在某個網絡結點長時間的滯留了,以至延誤到鏈接釋放之後的某個時間纔到達server。原本這是一個早已失效的報文段。但server收到此失效的鏈接請求報文段後,就誤認爲是client再次發出的一個新的鏈接請求。因而就向client發出確認報文段,贊成創建鏈接。假設不採用「三次握手」,那麼只要server發出確認,新的鏈接就創建了。因爲如今client並無發出創建鏈接的請求,所以不會理睬server的確認,也不會向server發送數據。但server卻覺得新的運輸鏈接已經創建,並一直等待client發來數據。這樣,server的不少資源就白白浪費掉了。採用「三次握手」的辦法能夠防止上述現象發生。例如剛纔那種狀況,client不會向server的確認發出確認。server因爲收不到確認,就知道client並無要求創建鏈接。」
二、網絡故障
好比,如今網絡出現了故障,只能發請求數據包,而接收不到響應數據包,那麼只要發送一次請求,服務器就創建請求,這樣確定也是不對的,網絡請求有來有回才能完成通信。因此三次握手是必不可少的。
TCP協議是一種面向鏈接的、可靠的、基於字節流的運輸層通訊協議。TCP是全雙工模式,這就意味着,當 Client 發出FIN報文段時,只是表示 Client 已經沒有數據要發送了,Client 告訴 Server,它的數據已經所有發送完畢了;可是,這個時候 Client 仍是能夠接受來自 Server 的數據;當 Server 返回ACK報文段時,表示它已經知道 Client 沒有數據發送了,可是 Server 仍是能夠發送數據到 Client 的;當 Server 也發送了FIN報文段時,這個時候就表示 Server 也沒有數據要發送了,就會告訴 Client ,我也沒有數據要發送了,以後彼此就會愉快的中斷此次TCP鏈接。若是要正確的理解四次分手的原理,就須要瞭解四次分手過程當中的狀態變化。