聊清楚TCP三次握手四次揮手
目錄
前言
TCP:傳輸控制協(xié)議
TCP簡介
TCP首部
TCP連接的建立和終止
三次握手
四次揮手
TCP的狀態(tài)變遷圖
2MSL等待狀態(tài)
FIN_WAIT_2狀態(tài)
最大報文段長度
TCP的半關(guān)閉
兩端同時打開
兩端同時關(guān)閉
復位報文段
前言
上周記錄了一下DNS的相關(guān)信息,包含DNS服務(wù)器的分類、如何利用DNS將域名轉(zhuǎn)換成真實的IP等信息
今天就來記錄一下TCP的三次握手四次揮手究竟是怎么樣的?以及為什么在四次揮手中會存在TIME_WAIT狀態(tài)?
TCP:傳輸控制協(xié)議
TCP簡介
TCP提供一種面向連接的、可靠的字節(jié)流服務(wù)。
面向連接是指兩個使用TCP的應(yīng)用在彼此交換數(shù)據(jù)之前必須先建立一個TCP連接。
其可靠性體現(xiàn)在如下幾個方面:
應(yīng)用數(shù)據(jù)分片 超時重傳 數(shù)據(jù)接收確認 保持首部和數(shù)據(jù)的校驗和 數(shù)據(jù)接收后進行重排序 丟棄重復數(shù)據(jù) 流量控制 擁塞控制
TCP首部
TCP數(shù)據(jù)依舊是封裝在IP數(shù)據(jù)報中的

TCP首部詳細

一個IP地址和一個端口號也稱為一個插口,插口對(包含客戶端服務(wù)端端口號、IP的四元組)可唯一確定互聯(lián)網(wǎng)絡(luò)中的每個TCP連接的雙方。
序號用來標識從TCP發(fā)端向TCP收端發(fā)送的數(shù)據(jù)字節(jié)流,它表示在這個報文段中的的第一個數(shù)據(jù)字節(jié)。如果將字節(jié)流看作在兩個應(yīng)用程序間的單向流動,則TCP用序號對每個字節(jié)進行計數(shù)。序號是32bit的無符號數(shù),序號到達232-1后又從0開始。
當新建一個新的連接時,SYN標志變?yōu)?
每個傳輸?shù)淖止?jié)都被計數(shù),確認序號包含發(fā)送確認的一端所期望收到的下一個序號。
確認序號是上次已成功收到數(shù)據(jù)字節(jié)序號加1。(例如第一次傳輸0~1024,那么確認序號就是1025)只有ACK標志為1025時確認序號字段才有效。
TCP為應(yīng)用層提供全雙工服務(wù)。這意味數(shù)據(jù)能在兩個方向上獨立地進行傳輸。
檢驗和覆蓋了整個的TCP報文段TCP首部和TCP數(shù)據(jù)。這是一個強制性的字段,一定是由發(fā)端計算和存儲,并由收端進行驗證。TCP檢驗和的計算和UDP檢驗和的計算相似,使用一個偽首部。
首部長度給出首部中32bit字的數(shù)目。需要這個值是因為任選字段的長度是可變的。這個字段占4bit,因此TCP最多有60字節(jié)的首部。
URG 緊急指針有效 ACK 確認序號有效。 PSH 接收方應(yīng)該盡快將這個報文段交給應(yīng)用層。 RST 重建連接。 SYN 同步序號用來發(fā)起一個連接。 FIN 發(fā)端完成發(fā)送任務(wù)
TCP連接的建立和終止
TCP是一個面向連接的協(xié)議,無論哪一方向另一方發(fā)送數(shù)據(jù)之前,都必須先在雙方之間建立一條連接。
TCP接受一個連接是將其放入隊列中,而應(yīng)用層接受一個連接是將其從該隊列中移出。
應(yīng)用層在三次握手中的第三個報文段收到之后才會知道有新的連接。
建立一條連接需要三次握手,而終止一條連接需要四次握手。

格式:
源 > 目的:標志

第一行中,字段1415531521:1415531521(0)表示分組的序號是1415531521,(0)表示數(shù)據(jù)字節(jié)數(shù)為0。
開始的序號:隱含的結(jié)尾序號(數(shù)據(jù)字節(jié)數(shù))。顯示序號和隱含結(jié)尾序號的優(yōu)點是便于了解數(shù)據(jù)字節(jié)數(shù)大于0時的隱含結(jié)尾序號,此字段是有在滿足條件報文段中至少包含一個數(shù)據(jù)字節(jié)或SYN、FIN或RST被設(shè)置為1的時候才顯示。
第二行中的ack為1415531522表示確認序號,只有在首部的ACK標志比特為1的時候才顯示。
win 4096表示發(fā)端通告的窗口大小,沒有數(shù)據(jù)交換,則默認為4096.
<mss 1024>表示由發(fā)端指明的最大報文段長度選項,發(fā)端將不接收超過此長度的TCP報文段。
三次握手
(1)客戶端發(fā)送一個SYN段指明客戶打算連接的服務(wù)器的端口號,以及初始序號(ISN,例如1415531521),這個SYN段為報文段1
(2)服務(wù)端發(fā)回包含服務(wù)端的初始序號的SYN報文段(報文段2)作為應(yīng)答。同時將確認序號設(shè)置為客戶端ISN加1以對客戶的SYN報文段進行確認,一個SYN將占用一個序號。
(3)客戶必須將確認序號設(shè)置為服務(wù)器的ISN加1以對服務(wù)器的SYN報文段進行確認

ESTABLISHED狀態(tài)是連接雙方能進行雙向數(shù)據(jù)傳遞的狀態(tài)。
例如:

當一端為建立連接而發(fā)送它的SYN時,為連接選擇一個初始序號,ISN隨時間而變化,因此每個連接都具有不同的ISN。
四次揮手
建立一個連接需要三次握手,終止一個連接需要四次揮手,這是由TCP的半關(guān)閉造成的。
既然TCP是全雙工的,因此每個方向必須單獨的進行關(guān)閉。
這原則就是當一方完成它的數(shù)據(jù)發(fā)送任務(wù)后就能發(fā)送一個FIN來終止這個方向的連接。當一端收到一個FIN,它必須通知應(yīng)用層另一端幾經(jīng)終止了那個方向的數(shù)據(jù)傳送。發(fā)送FIN通常是應(yīng)用層進行關(guān)閉的結(jié)果。

首先進行關(guān)閉的一方(即發(fā)送第一個FIN)將執(zhí)行主動關(guān)閉,而另一方(收到這個FIN)執(zhí)行被動關(guān)閉。通常一方完成主動關(guān)閉而另一方完成被動關(guān)閉,
當服務(wù)器收到這個FIN,它發(fā)回一個ACK,確認序號為收到的序號加1(報文段5)。和SYN一樣,一個FIN將占用一個序號。同時TCP服務(wù)器還向應(yīng)用程序(即丟棄服 務(wù)器)傳送一個文件結(jié)束符。接著這個服 務(wù)器程序就關(guān)閉它的連接,導致它的TCP端發(fā)送一個FIN(報文段6),客戶必須發(fā)回 一個確認,并將確認序號設(shè)置為收到序號 加1(報文段7)

TCP的狀態(tài)變遷圖

粗的實線箭頭表示正常的客戶端狀態(tài)變遷,用粗的虛線箭頭表示正常的服務(wù)器狀態(tài)變遷。
整個流程圖:

2MSL等待狀態(tài)
TIME_WAIT狀態(tài)也稱為2MSL等待狀態(tài)。
每個TCP實現(xiàn)必須選擇一個報文段最大生成時間(Maximum Segment Lifetime),是任何報文段在被丟棄前在網(wǎng)絡(luò)內(nèi)的最長時間。
RFC 793 [Postel 1981c] 指出MSL為2分鐘。然而,實現(xiàn)中的常用值是30秒,1分鐘, 或2分鐘。
TCP報文段在IP數(shù)據(jù)報中傳輸,IP數(shù)據(jù)報則有存活限制時間TTL字段。
對一個給定的MSL來說,當TCP執(zhí)行一個主動關(guān)閉,并發(fā)送最后一個ACK,該連接必須在TIME_WAIT狀態(tài)停留時間為2倍的MSL,可讓TCP再次發(fā)送最后的ACK以防這個ACK丟失(另一端超時并重發(fā)最后的FIN)。

就比如上述這個圖,當服務(wù)端發(fā)送LAST_ACK的時候,客戶端就處于了TIME_WATI狀態(tài),此時客戶但必須在這個狀態(tài)保持2MSL時間,為的是客戶端在發(fā)送最后一個ACK給服務(wù)端的時候,服務(wù)端在2MSL時間內(nèi)沒收到這個ACK的話,服務(wù)端會重新發(fā)送LAST_ACK,而之前那個LAST_ACK就被丟棄
這種2MSL等待的另一個結(jié)果是這個TCP連接在2MSL等待器間,此連接涉及的四元組(客戶端IP、port,服務(wù)器IP、port)不能再被使用,只有2MSL結(jié)束后才能再被使用。
不過在實際應(yīng)用中可以通過設(shè)置SO_REUSEADDR選項達到不必等待2MSL時間結(jié)束再使用此端口。
TIME_WAIT狀態(tài)的影響:
在高并發(fā)的狀態(tài)下會有大量 time_wait 狀態(tài)存在,會導致新建 TCP 連接會出錯,address already in use : connect 異常
解決方法:
1.客戶端,HTTP 請求的頭部,connection 設(shè)置為 keep-alive,保持存活一段時間:現(xiàn)在的瀏覽器,一般都這么進行了
2.服務(wù)器端允許time_wait狀態(tài)的socket被重用,縮減time_wait時間,設(shè)置為1MSL(即,2 mins)
FIN_WAIT_2狀態(tài)
客戶端已經(jīng)發(fā)出了FIN,并且服務(wù)端也已對它進行確認。
只有當另一端的進程完成這個關(guān)閉,客戶端才會從FIN_WAIT_2狀態(tài)進入TIME_WAIT狀態(tài)
最大報文段長度
最大報文段長度(MSS)表示TCP傳往另一端的最大塊數(shù)據(jù)的長度,當一個連接建立時,連接的雙方都要通告各自的MSS。
MSS字段只能出現(xiàn)在SYN報文段中
如果目的IP地址是非本地的,MSS通常默認值是536。
如何判斷是否本地:
(1)網(wǎng)絡(luò)號和子網(wǎng)號一樣,是本地
(2)網(wǎng)絡(luò)號和子網(wǎng)號都不一樣,非本地
(3)網(wǎng)絡(luò)號一樣,子網(wǎng)號不一樣,本地非本地都有可能
MSS讓主機限制另一端發(fā)送數(shù)據(jù)報的長度,加上主機也能控制它發(fā)送數(shù)據(jù)報的長度,這將使以較小MTU連接到一個網(wǎng)絡(luò)上的主機避免分段。
一般MSS是MTU減去20字節(jié)的IP首部和20字節(jié)的TCP首部。
TCP的半關(guān)閉
TCP提供了連接的一端在結(jié)束它的發(fā)送后還能接收來自另一端數(shù)據(jù)的能力,這就是半關(guān)閉。

兩端同時打開
需要進行4次握手,比正常多一次

兩端同時關(guān)閉

復位報文段
TCP首部中的RST比特是用于“復位”的。一般說來,無論何時一個報文。段發(fā)往基準的連接( referenced connection)出現(xiàn)錯誤,TCP都會發(fā)出一個復位報文段(這里提到的“基準的連接”是指由目的IP地址和目的端口號以及源IP地址和源端口號指明的連接)。
產(chǎn)生復位的一種常見情況是當連接請求到達時,目的端口沒有進程正在聽。對于 UDP,當一個數(shù)據(jù)報到達目的端口時,該端口沒在使用,它將產(chǎn)生一個ICMP端口不可達的信息。而TCP則使用復位。
異常終止一個連接,或者檢測半打開連接都需要發(fā)送一個復位報文段。

往期推薦:
DNS域名解析系統(tǒng)
