TCP協議之三次握手與四次揮手

TCP協議是TCP/IP體系中核心一個協議,該協議比起IP協議,ICMP協議,UDP協議都更復雜,所以這篇文章主要分析TCP協議在創建鏈接和斷開鏈接的時候,狀態轉移以及報文段的內容。
下面,先放一張TCP的狀態轉移圖:網絡

center

TCP協議之三次握手

三次握手的過程是TCP在客戶端和服務端創建鏈接的過程。簡單的來講三次握手過程,就是客戶端先發送一個鏈接請求給服務端,這是第一次握手。服務端接收到客戶端發來的連接請求,而後在將確認的消息發給客戶端,這是第二次握手。客戶端對服務端發來的確認消息進行確認,而後將確認的消息發給服務端,這就是三次握手。三次握手以後,連接創建。
爲何必定是三次握手才能創建一個可靠地連接?若是不是三次握手,那麼在客戶端發送了連接請求以後,服務端對這個請求進行確認,就認定此次的連接已經成功創建,俗稱的二次握手。這樣的方式的弊端在哪裏?
考慮這麼一種狀況,當客戶端進行第一次握手時,發送了一個報文段,可是這個報文段由於網絡的問題,遲遲沒有到,這時,客戶端又會再一次發送一個鏈接請求的報文段給服務端,此次成功接收,二者創建鏈接,並通訊結束,關閉鏈接。這以後,由於網絡延遲的那個報文段傳到了服務端那裏,服務端又覺得客戶端要創建新的鏈接,因而就贊成了,向客戶端發送確認。由於是二次握手,因此服務端後續要作的事情,就是等待客戶端發送的消息,可是客戶端是不會理會服務端傳來的確認,因此服務端就會一直在等待客戶端的數據,白白浪費了資源。tcp

抓包分析TCP三次握手的報文段

如今,詳細說一下三次握手具體是作了什麼。
第一次握手,客戶端發送一個報文段給服務端,該報文段中標誌有SYN標誌,該標誌表示創建鏈接,以及一個初始的序列號。
第二次握手時,服務端發送一個報文段給客戶端,該報文段中標誌有SYN標誌,和ACK標誌。ACK標誌的值是客戶端發來的初始序號值+ 1,表示對客戶端進行確認,報文段中還有服務端本身的初始序號。
第三次握手時,客戶端發送一個報文段給服務端,該報文段中標誌只有ACK標誌,該ACK值是服務端的初始序列化的值 + 1,表示對服務端進行確認,以及還有一個序號值,該序號值爲客戶端第一次握手時的序號值 + 1。
三次握手創建鏈接結束。

圖片上共有三行,每一行表明一次握手。咱們先看第一行

能夠看出,第一次握手時55732端口的程序主動發送一個創建連接的報文段給8888端口。這個55732端口是Java程序寫的一個Socket客戶端,8888端口是Socket程序寫的服務端。創建鏈接的報文段,Flags中,只有SYN是爲1的,這代表這是一個創建鏈接的報文段,該報文段中初始的序列號爲0,ACK的number也爲0。

第二次握手,是服務端發送給客戶端一個報文段,表示確認收到了客戶端的連接請求。該報文段中標誌位有兩個一個是ACK,一個SYN。表示收到連接請求,端口開放。該報文段中也會發送一個服務端本身的初始序列號。注意,這裏ACK的值變成了1,是客戶端初始序列號 + 1纔有的。

第三次握手,是客戶端發送給服務端一個報文段,表示確認收到了服務端的確認。由於雙方端口都已經打開,因此客戶端在發,就不會再有SYN標誌了,這裏只有ACK標誌,該標誌的值也是1,是由於服務端的初始序列號 + 1形成的。這裏的序列號爲1,是由於第一次握手,發送了一個SYN標誌,該標誌會佔用1個序號值,可是ACK不會。
對應到上面的狀態圖中,就是客戶端是主動打開,從起始點發送SYN報文段,進入SYN_SENT狀態,而後接受SYN,ACK,走黑粗線的路徑進入到數據傳輸狀態,也就是ESTABLISHED,對於服務端而言,就是從起始點走虛線的部分,被動打開後,接受客戶端的SYN,進入SYN_RCVD,最後,接受客戶端第三次握手的ACK,進入數據傳輸狀態,也就是ESTABLISHED。3d

TCP協議之四次揮手

TCP協議是一種全雙工協議,擁有半關閉的特性。blog

全雙工的意思是A能夠往B發送數據,B同時也能夠給A發送數據。
半雙工的意思是A能夠往B發送數據,B也能夠給A發送數據,可是二者不能同時。
單工的意思是隻能A給B發送數據,或者B給A發送數據。
半關閉的意思是將全雙工,變成單工,也就是若是B關閉,是指B不能給A發數據了,可是A能夠給B發圖片

因此TCP協議若是要正常的關閉客戶端與服務端的連接,須要四次報文段,也就是4次揮手。
首先,客戶端由於應用程序的執行完畢,會主動開始斷開連接,這時會發送一個含有FIN標誌位的報文段。這代表客戶端不會再發送數據給服務端。這時第一次揮手。
而後,服務端接收到這個報文段,就會發送一個含有ACK標誌的報文段給客戶端,表示確認收到了關閉的報文段。這是第二次揮手。
而後,服務端在處理完服務端的事情後,也會發送一個含有FIN的報文段給客戶端,表示服務端不會再發送數據給客戶端。這是第三次揮手。
最後,客戶端收到這個報文段後,就會發送一個含有ACK的報文段給服務端,表示確認收到了關閉的報文段。這是第四次揮手。至此,連接所有關閉。資源

抓包分析TCP四次揮手的報文段


不用看黑色報文,4行表明關閉的4次揮手的過程,每一行是一次揮手。
第一行,是客戶端主動關閉連接,發送一個含有FIN的報文段,這是第一次揮手
第二行,是服務端確認客戶端的FIN報文,發送一個ACK的確認報文,該ACK的值是9,而第一行的序列號的8,由於與SYN同樣,FIN也佔一個序列號。
忽略黑的後第三行,服務端發送一個含有FIN的報文段,這是第三次揮手。
第四行,客戶端會這個FIN報文段進行確認,發送了一個ACK報文段。該ACK的值是第三行的序列號 + 1。序列化

對應到上面的狀態圖中,先說服務端的狀態轉移,由於收到了客戶端的FIN,因此發送一個ACK給客戶端,同時本身進入到CLOSE_WAIT狀態,等待服務端應用程序結束,發送FIN給客戶端,本身進入LAST_ACK狀態,等待最後的ACK到來,接收到ACK,結束狀態。請求

客戶端由於先發起關閉,狀態比較複雜,他先發送一個FIN給服務端,本身進入了FIN_WAIT_1狀態,這時他等待接收服務端的報文,該報文會有三種可能:程序

  1. 只有服務端的ACK
  2. 只有服務端的FIN
  3. 基於服務端的ACK,又有FIN

對於第一種,該ACK是服務端確認了客戶端的FIN而發的,這時客戶端會進入FIN_WAIT_2狀態,這是當他收到服務端的FIN來時,發送了一個ACK,會進入到TIME_WAIT狀態,他要在這個狀態等待2MSL的時間,1個MSL是報文段在網絡的最長時間,客戶端等待2MSL,是爲了當最後一個ACK丟失時,能夠在發送一次,由於這時,服務端在等待超時後在發送一個FIN給客戶端,因此客戶端也知道了ACK丟失了。im

對於第二種,只有服務端的FIN的時,會發送一個ACK給服務端,客戶端進入CLOSING狀態,而後接收到服務端的ACK時,也會進入TIME_WAIT狀態。

對於第三種,同時都收到了,就省略了進入CLOSING狀態,直接進入TIME_WAIT狀態。抓包分析的截圖,就是這種狀況。

相關文章
相關標籤/搜索