TCP通訊的三次握手和四次撒手的詳細流程(頓悟)

TCP(Transmission Control Protocol) 傳輸控制協議服務器

三次握手網絡

TCP是主機對主機層的傳輸控制協議,提供可靠的鏈接服務,採用三次握手確認創建一個鏈接:併發

位碼即tcp標誌位,有6種標示:SYN(synchronous創建聯機) ACK(acknowledgement 確認) PSH(push傳送) FIN(finish結束) RST(reset重置) URG(urgent緊急)tcp

Sequence number(順序號碼) Acknowledge number(確認號碼)測試

第一次握手:主機A發送位碼爲syn=1,隨機產生seq number=1234567的數據包到服務器,主機B由SYN=1知道,A要求創建聯機;spa

第二次握手:主機B收到請求後要確認聯機信息,向A發送ack number=(主機A的seq+1),syn=1,ack=1,隨機產生seq=7654321的包3d

第三次握手:主機A收到後檢查ack number是否正確,即第一次發送的seq number+1,以及位碼ack是否爲1,若正確,主機A會再發送ack number=(主機B的seq+1),ack=1,主機B收到後確認seq值與ack=1則鏈接創建成功。blog

完成三次握手,主機A與主機B開始傳送數據。開發


在TCP/IP協議中,TCP協議提供可靠的鏈接服務,採用三次握手創建一個鏈接。 
第一次握手:創建鏈接時,客戶端發送syn包(syn=j)到服務器,並進入SYN_SEND狀態,等待服務器確認; 
第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時本身也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態; 第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。 完成三次握手,客戶端與服務器開始傳送數據.
同步

實例:

IP 192.168.1.116.3337 > 192.168.1.123.7788: S 3626544836:3626544836
IP 192.168.1.123.7788 > 192.168.1.116.3337: S 1739326486:1739326486 ack 3626544837
IP 192.168.1.116.3337 > 192.168.1.123.7788: ack 1739326487,ack 1

第一次握手:192.168.1.116發送位碼syn=1,隨機產生seq number=3626544836的數據包到192.168.1.123,192.168.1.123由SYN=1知道192.168.1.116要求創建聯機;

第二次握手:192.168.1.123收到請求後要確認聯機信息,向192.168.1.116發送ack number=3626544837,syn=1,ack=1,隨機產生seq=1739326486的包;

第三次握手:192.168.1.116收到後檢查ack number是否正確,即第一次發送的seq number+1,以及位碼ack是否爲1,若正確,192.168.1.116會再發送ack number=1739326487,ack=1,192.168.1.123收到後確認seq=seq+1,ack=1則鏈接創建成功。

 

圖解:
一個三次握手的過程(圖1,圖2)

 

(圖1)

(圖2)
 

 

第一次握手的標誌位(圖3)
咱們能夠看到標誌位裏面只有個同步位,也就是在作請求(SYN)
3 
 (圖3)

第二次握手的標誌位(圖4)
咱們能夠看到標誌位裏面有個確認位和同步位,也就是在作應答(SYN + ACK)
4 
(圖4)

第三次握手的標誌位(圖5)
咱們能夠看到標誌位裏面只有個確認位,也就是再作再次確認(ACK)
5 
 
(圖5)

一個完整的三次握手也就是 請求---應答---再次確認

四次分手:
 
因爲 TCP鏈接是全雙工的,所以每一個方向都必須單獨進行關閉。這個原則是當一方完成它的數據發送任務後就能發送一個 FIN來終止這個方向的鏈接。收到一個  FIN只意味着這一方向上沒有數據流動,一個 TCP鏈接在收到一個 FIN後仍能發送數據。首先進行關閉的一方將執行主動關閉,而另外一方執行被動關閉。
 
1)客戶端 A發送一個 FIN,用來關閉客戶 A到服務器 B的數據傳送(報文段 4)。
2)服務器 B收到這個 FIN,它發回一個 ACK,確認序號爲收到的序號加 1(報文段 5)。和 SYN同樣,一個 FIN將佔用一個序號。
3)服務器 B關閉與客戶端 A的鏈接,發送一個 FIN給客戶端 A(報文段 6)。
4)客戶端 A發回 ACK報文確認,並將確認序號設置爲收到序號加 1(報文段 7)。
 
        狀態詳解:
 
        CLOSED: 這個沒什麼好說的了,表示初始狀態。
 
  LISTEN: 這個也是很是容易理解的一個狀態,表示服務器端的某個SOCKET處於監聽狀態,能夠接受鏈接了。
 
   SYN_RCVD: 這個狀態表示接受到了SYN報文,在正常狀況下,這個狀態是服務器端的SOCKET在創建TCP鏈接時的三次握手會話過程當中的一箇中間狀態,很短暫,基本 上用netstat你是很難看到這種狀態的,除非你特地寫了一個客戶端測試程序,故意將三次TCP握手過程當中最後一個ACK報文不予發送。所以這種狀態 時,當收到客戶端的ACK報文後,它會進入到ESTABLISHED狀態。
 
  SYN_SENT: 這個狀態與SYN_RCVD遙想呼應,當客戶端SOCKET執行CONNECT鏈接時,它首先發送SYN報文,所以也隨即它會進入到了SYN_SENT狀態,並等待服務端的發送三次握手中的第2個報文。SYN_SENT狀態表示客戶端已發送SYN報文。
 
   ESTABLISHED:這個容易理解了,表示鏈接已經創建了。
 
   FIN_WAIT_1: 這個狀態要好好解釋一下,其實FIN_WAIT_1和FIN_WAIT_2狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別 是:FIN_WAIT_1狀態其實是當SOCKET在ESTABLISHED狀態時,它想主動關閉鏈接,向對方發送了FIN報文,此時該SOCKET即 進入到FIN_WAIT_1狀態。而當對方迴應ACK報文後,則進入到FIN_WAIT_2狀態,固然在實際的正常狀況下,不管對方何種狀況下,都應該馬 上回應ACK報文,因此FIN_WAIT_1狀態通常是比較難見到的,而FIN_WAIT_2狀態還有時經常能夠用netstat看到。
   FIN_WAIT_2:上面已經詳細解釋了這種狀態,實際上FIN_WAIT_2狀態下的SOCKET,表示半鏈接,也即有一方要求close鏈接,但另外還告訴對方,我暫時還有點數據須要傳送給你,稍後再關閉鏈接。
   TIME_WAIT: 表示收到了對方的FIN報文,併發送出了ACK報文,就等2MSL後便可回到CLOSED可用狀態了。若是FIN_WAIT_1狀態下,收到了對方同時帶FIN標誌和ACK標誌的報文時,能夠直接進入到TIME_WAIT狀態,而無須通過FIN_WAIT_2狀態。
  CLOSING: 這種狀態比較特殊,實際狀況中應該是不多見,屬於一種比較罕見的例外狀態。正常狀況下,當你發送FIN報文後,按理來講是應該先收到(或同時收到)對方的 ACK報文,再收到對方的FIN報文。可是CLOSING狀態表示你發送FIN報文後,並無收到對方的ACK報文,反而卻也收到了對方的FIN報文。什 麼狀況下會出現此種狀況呢?其實細想一下,也不可貴出結論:那就是若是雙方几乎在同時close一個SOCKET的話,那麼就出現了雙方同時發送FIN報 文的狀況,也即會出現CLOSING狀態,表示雙方都正在關閉SOCKET鏈接。
   CLOSE_WAIT: 這種狀態的含義實際上是表示在等待關閉。怎麼理解呢?當對方close一個SOCKET後發送FIN報文給本身,你係統毫無疑問地會迴應一個ACK報文給對 方,此時則進入到CLOSE_WAIT狀態。接下來呢,實際上你真正須要考慮的事情是察看你是否還有數據發送給對方,若是沒有的話,那麼你也就能夠 close這個SOCKET,發送FIN報文給對方,也即關閉鏈接。因此你在CLOSE_WAIT狀態下,須要完成的事情是等待你去關閉鏈接。
   LAST_ACK: 這個狀態仍是比較容易好理解的,它是被動關閉一方在發送FIN報文後,最後等待對方的ACK報文。當收到ACK報文後,也便可以進入到CLOSED可用狀態了。
 
 
總結:
 
1.爲何創建鏈接協議是三次握手,而關閉鏈接倒是四次握手呢?
 
這是由於服務端的 LISTEN狀態下的 SOCKET當收到 SYN報文的建連請求後,它能夠把 ACKSYNACK起應答做用,而 SYN起同步做用)放在一個報文裏來發送。但關閉鏈接時,當收到對方的 FIN報文通知時,它僅僅表示對方沒有數據發送給你了;但未必你全部的數據都所有發送給對方了,因此你能夠未必會立刻會關閉 SOCKET,也即你可能還須要發送一些數據給對方以後,再發送 FIN報文給對方來表示你贊成如今能夠關閉鏈接了,因此它這裏的 ACK報文和 FIN報文多數狀況下都是分開發送的.
 
2.爲何TIME_WAIT狀態還須要等2MSL後才能返回到CLOSED狀態?
 
這是由於雖然雙方都贊成關閉鏈接了,並且握手的 4個報文也都協調和發送完畢,按理能夠直接回到 CLOSED狀態(就比如從 SYN_SEND狀態到 ESTABLISH狀態那樣);可是由於咱們必需要假想網絡是不可靠的,你沒法保證你最後發送的 ACK報文會必定被對方收到,所以對方處於 LAST_ACK狀態下的 SOCKET可能會由於超時未收到 ACK報文,而重發 FIN報文,因此這個 TIME_WAIT狀態的做用就是用來重發可能丟失的 ACK報文。
相關文章
相關標籤/搜索