在使用TCP協議進行數據的傳輸以前,客戶端與服務器端須要創建TCP Connection,即創建鏈接,以後兩端才能進行數據的傳輸。服務器
下面堆TCP鏈接「三次握手」的過程進行說明。post
一、相關概念性能
首先,咱們須要瞭解TCP數據報的首部的結構(TCP數據報包括首部以及數據報部分),以下圖:spa
其中須要注意的字段有:blog
(1)序號(sequence number):seq序號,佔32位4個字節。從TCP源端向目的端發送的字節流數據,發起方發送數據報文時對每個字節進行編號標記,每個字節都會有一個編號(0 到 232-1)。給報文每一個字節編上序號後,須要給報文指派一個序號seq,報文數據段的第一個字節的編號值,就是這段報文TCP首部序號seq的值。get
(2)確認號(acknowledgement number):ack序號,佔32位4個字節。表示期待收到對方下一個報文段的序號,那麼第一次收到的報文段最後一個字節的編號+1即爲確認號。好比第一段報文seq=1(報文第一個字節編號1),報文長度是100,即報文最後一個字節編號爲100。確認端接收到發起端發送的報文後,返回給發起端的響應TCP報文中,ACK=1,ack=101,表示發起端發送的1-100編號的字節數據已經收到,但願發起端下一個報文從101編號的字節開始發送。同步
注意,只有TCP報文的ACK標誌位爲1時,這個報文中的確認序號字段纔有效。it
(3)標誌位(Flags):TCP標誌物有6位,具體以下圖io
i)確認ACK:佔1位,僅當ACK=1時,確認號字段纔有效;ACK=0時,確認號無效 。基礎
ii)同步SYN:用於創建鏈接的同步標記。當SYN=1,ACK=0時表示這是一個鏈接請求報文段。若贊成鏈接,則在響應報文段中使得SYN=1,ACK=1。所以,SYN=1表示這是一個鏈接請求報文。
iii)終止FIN:用來釋放一個鏈接。FIN=1表示此報文段的客戶端的數據已經發送完畢,並要求釋放鏈接。
這裏須要注意2點:
1)不要混淆ACK標誌位與ack確認號;
2)SYN這個標誌位只有在TCP建立鏈接時纔會被置1,握手完成後SYN標誌位被置0。
二、三次握手過程
過程以下圖:
注意,此處所謂的「客戶端」與「服務器端」,只是爲了方便標識鏈接的雙方,即確認哪一方是「要求斷開鏈接」的主動方,哪一方是「要求斷開鏈接」的被動方。事實上任何一方均可能要求創建鏈接。
步驟以下:
1)首先客戶端向服務器端發送一段TCP報文,其中:
i)標記位爲SYN=1,表示「請求創建新鏈接」;
ii)序號爲 seq = x,表示客戶端發送給服務器端的數據報文的序號是 x ,即數據報文的第一個字節的編號爲 x。注意,創建鏈接的SYN報文雖然沒有數據,可是會佔用一個序號的大小;
iii)此時,客戶端進入 SYNC-SENT 狀態:同步已發送狀態。
2)服務器端接收到來自客戶端 TCP 報文以後,返回一段TCP報文,其中:
i)標誌位爲 SYN 和 ACK ,ACK=1 是確認標誌,表示 「確認客戶端的報文seq序號有效,服務器端能正常接收客戶端發送的數據。即告訴客戶端,服務器端收到了它的請求報文」,SYN=1 是請求鏈接標誌,表示「服務器端贊成建立新鏈接」。ACK與SYN 合起來,就是告訴客戶端,服務器端 收到了你的數據,贊成與你創建鏈接;
ii)ack=x+1,表示但願客戶端下一次發送回來的數據報序號是 x+1;
iii)seq = y,服務器端向客戶端發送本身的數據報,序號是 y。
iv)同時,服務器端結束 LISTEN 監聽階段,進入 SYNC-RCVD 同步已接收狀態。
3)客戶端接收到來自服務器端的確認收到數據的TCP報文以後,明確了從客戶端到服務器端的數據傳輸是正常的,能夠創建鏈接。返回一段TCP報文,其中:
i)標誌位爲ACK,表示 「確認收到服務器端贊成鏈接的信號」(即告訴服務器端,我知道你收到我發的數據了);
ii)seq=x+1,表示向服務器端發送序號爲x+1的數據,根據第二次握手的 ack=x+1,將seq設置爲 x+1;
iii)ack=y+1,表示但願服務器端下一次發送回來的數據報序號爲y+1。
iv)隨後它會進入 ESTABLISHED 創建鏈接階段。
4)服務器端在接收到客戶端發送的第三次握手的數據後,也會進入 ESTABLISHED 創建鏈接階段。
在「三次握手」中,經過第1、第二次握手的SYN,客戶端與服務器端創建鏈接;並且經過第2、第三次握手的ACK,雙方都確認對方已經收到本身的報文。客戶端與服務器端的 ack 與 seq 的值,都是在對方 ack 與 seq 值的基礎上計算的,即經過「三次握手」,客戶端與服務器端也同步了各自的序號與確認號。這樣作保證了TCP報文的連貫性,一旦有一方的報文丟失,另外一方便沒法正確「握手」(由於想正確握手,發出的 seq 須要與對方發來的 ack 相同)。
三、爲何要進行「三次握手」才能創建TCP鏈接
緣由:避免已經失效的鏈接請求報文傳送到服務器端,致使服務器端開啓一些無效的鏈接,增長服務器端開銷。
分析以下圖:
若是是三次握手,就能夠避免上面這種狀況的發生,以下圖:
四、擴展
在客戶端與服務器端創建鏈接以後,在這個鏈接上,客戶端與服務器端之間能夠發送的HTTP請求數量與使用的HTTP協議的版本相關。
1)HTTP1.0版本:TCP鏈接是在HTTP請求建立的時候同步建立的,HTTP請求發送到服務器端,服務器端響應了以後,這個TCP鏈接就關閉了。即一次鏈接只能發送一次HTTP請求;
2)HTTP1.1版本:三次握手創建TCP鏈接後,以某種方式聲明這個鏈接一直保持,後面的HTTP請求能夠繼續使用這個鏈接。
因爲在建立一個TCP鏈接的過程當中須要「三次握手」的性能消耗。若是每次HTTP請求都要從新創建TCP鏈接,那麼每次HTTP請求都有「三次握手」的性能消耗。若是使用HTTP1.1,只有第一次請求須要創建鏈接,後面的請求不須要創建鏈接,則只有一次「三次握手」的消耗。
「四次揮手」請參考文章:https://i.cnblogs.com/posts/edit;postId=13067989