先了解一下TCP頭部數據結構的關鍵概念:
序列號seq:
佔4個字節,用來標記數據段的順序,TCP把連接中發送的所有數據字節都編上一個序號,第一個字節的編號由本地隨機產生;給字節編上序號後,就給每一個報文段指派一個序號;序列號seq就是這個報文段中的第一個字節的數據編號。
確認號ack:
佔4個字節,期待收到對方下一個報文段的第一個數據字節的序號;序列號表示報文段攜帶數據的第一個字節的編號;而確認號指的是期望接收到下一個字節的編號;因此當前報文段最後一個字節的編號+1即爲確認號。
主要標誌位
字段 | 含義 |
---|---|
ACK | 確認號是否有效,僅當ACK=1時,確認號字段纔有效。ACK=0時,確認號無效 |
SYN | 連接建立時用於同步序號。當SYN=1,ACK=0時表示:這是一個連接請求報文段。若同意連接,則在響應報文段中使得SYN=1,ACK=1。因此,SYN=1表示這是一個連接請求,或連接接受報文。SYN這個標誌位只有在TCP建產連接時纔會被置1,握手完成後SYN標誌位被置0 |
FIN | 用來釋放一個連接。FIN=1表示:此報文段的發送方的數據已經發送完畢,並要求釋放運輸連接 |
URG | 緊急指針是否有效。爲1,表示某一位需要被優先處理 |
PSH | 提示接收端應用程序立即從TCP緩衝區把數據讀走 |
RST | 對方要求重新建立連接,復位 |
三次握手過程
TCP三次握手過程 | |
---|---|
第一次握手 | 客戶端發送 SYN 包 (syn=x) 到服務器,並進入 SYN_SEND 狀態,等待服務器確認; |
第二次握手 | 服務器收到 SYN 包,必須確認客戶的 SYN(ack=x+1),同時自己也發送一個 SYN 包(syn=y),即 SYN+ACK 包,此時服務器進入 SYN_RECV 狀態; |
第三次握手 | 客戶端收到服務器的 SYN+ACK 包,向服務器發送確認包 ACK(ack=y+1),此包發送完畢,客戶端和服務器進入 ESTABLISHED 狀態,完成三次握手。 |
握手過程中傳送的包裏不包含數據,三次握手完畢後,客戶端與服務器才正式開始傳送數據。理想狀態下,TCP連接一旦建立,在通信雙方中的任何一方主動關閉連接之前,TCP 連接都將被一直保持下去。
通俗的總結三次握手的目的和結果:
第一次握手:客戶端發送連接請求到服務端,服務端收到請求後,確認了客戶端可以正常發送數據,同時也確認了自己可以正常接收客戶端的數據;
接下來進行第二次握手:服務端發送應答包給客戶端,客戶端收到應答包後,就可以確認自己可以正常發送數據給服務端(因爲自己的請求被服務端接收到了),同時也確認了服務端可以正常發送數據給自己;
通過前面兩次的握手,客戶端知道了自己可以發送數據到服務端也可以接收服務端的數據,但服務端只知道自己可以接收客戶端的數據,不知道能不能發送數據給客戶端,所以需要進行第三次握手:客戶端再次發送應答包給服務端,服務端收到之後就確認了自己可以正常發送數據給客戶端;
所以需要三次握手來確認了客戶端和服務端的接收和發送能力,而無需進行第四次,同時也說明了兩次握手無法確認雙發的發送和接收能力。
四次揮手過程
TCP四次揮手過程 | |
---|---|
第一次揮手 | 主動關閉方發送一個 FIN,用來關閉主動方到被動關閉方的數據傳送,也就是主動關閉方告訴被動關閉方:我已經不 會再給你發數據了(當然,在fin包之前發送出去的數據,如果沒有收到對應的ack確認報文,主動關閉方依然會重發這些數據),但是,此時主動關閉方還可 以接受數據。 |
第二次揮手 | 被動關閉方收到 FIN 包後,發送一個 ACK 給對方,確認序號爲收到序號+1(與 SYN 相同,一個 FIN 佔用一個序號) |
第三次揮手 | 被動關閉方發送一個 FIN,用來關閉被動關閉方到主動關閉方的數據傳送,也就是告訴主動關閉方,我的數據也發送完了,不會再給你發數據了。 |
第四次揮手 | 主動關閉方收到 FIN 後,發送一個 ACK 給被動關閉方,確認序號爲收到序號+1,至此,完成四次揮手。 |