三次握手建立連接
- 客戶主機發(fā)送請求報文,F(xiàn)lag設(shè)置為 SYN,帶上 Seq, 假設(shè)為 clientNo;
- 服務(wù)主機接收到報文后,為這次連接分配資源,并回復(fù)報文, Flag設(shè)置為 [SYN, ACK], 帶上 Seq, 假設(shè)為 serverNo,同時帶上 Ack,為clientNo + 1;
- 客戶主機收到報文后,為鏈接分配資源,也會發(fā)送回復(fù)報文,F(xiàn)lag設(shè)置為 ACK, 帶上 Seq,為 clientNo + 1, 并帶上 Ack,為 serverNo + 1。
三次握手后,TCP連接正式建立。具體流程如下圖所示:

四次揮手?jǐn)嚅_連接
- 客戶主機發(fā)送斷開連接請求(也可以是服務(wù)主機首先發(fā)送該請求,如 Http 服務(wù)器),發(fā)送報文,F(xiàn)lag設(shè)置為 FIN,并帶上 Seq,假設(shè)為 clientNo。發(fā)送該報文,可以通俗的理解為:客戶主機告訴服務(wù)主機,我們沒啥好說的了,你那邊沒什么異議的話,要不我們分手吧。
- 服務(wù)主機收到 Fin 報文后,發(fā)送回復(fù)報文,F(xiàn)lags設(shè)置為 ACK,帶上Seq,假設(shè)為 serverNo1,同時帶上 Ack,為clientNo + 1??梢酝ㄋ椎睦斫鉃椋何叶愕囊馑剂耍屛蚁葴?zhǔn)備準(zhǔn)備先。此時,提出分手的主機進入 FIN_WAIT 狀態(tài),等待服務(wù)主機的分手報文。
- 服務(wù)主機確定數(shù)據(jù)已經(jīng)發(fā)送完成,則向客戶主機發(fā)送斷開報文,F(xiàn)lag設(shè)置為 FIN,并帶上 Seq,假設(shè)為 serverNo2。可以理解為:碧池,我這邊事情完結(jié)了,我們可以分手了。
- 客戶主機收到 FIN 報文后,知道可以關(guān)閉網(wǎng)絡(luò),發(fā)送回復(fù)報文,設(shè)置Flags為 ACK,帶上Seq為clientNo2,Ack為ServerNo2 + 1,之后進入 TIME_WAIT狀態(tài),如果 2MSL 后,服務(wù)主機沒有回應(yīng),說明服務(wù)主機已經(jīng)正常關(guān)閉,客戶主機也關(guān)閉連接。
具體流程如下圖所示:

抓包實例
下圖是用 WireShark 對 HTTP 請求的抓包實例:

前三個包是三次握手,后四個包是四次揮手
三次握手
- 客戶端發(fā)送 SYN 包,Seq為0
- 服務(wù)端發(fā)送 [SYN, ACK] 包,Seq為0, Ack為1
- 客戶端發(fā)送 ACK 包,Seq為0, Ack為1
四次揮手
- 服務(wù)端發(fā)送 [FIN, ACK] 包,Seq為1226,F(xiàn)lags中的 ACK 不是用于關(guān)閉連接
- 客戶端發(fā)送 ACK 包,Seq為2031, Ack為1227
- 客戶端發(fā)送 [FIN, ACK] 包,Seq為2031
- 服務(wù)端發(fā)送 ACK 包,Seq為1227, Ack=2032
注意
什么要三次握手
在謝希仁的《計算機網(wǎng)絡(luò)》中是這樣說的:
為了防止已失效的連接請求報文段突然又傳送到了服務(wù)端,因而產(chǎn)生錯誤。
在書中同時舉了一個例子,如下:
“已失效的連接請求報文段”的產(chǎn)生在這樣一種情況下:client發(fā)出的第一個連接請求報文段并沒有丟失,而是在某個網(wǎng)絡(luò)結(jié)點長時間的滯留了,以致延誤到連接釋放以后的某個時間才到達(dá)server。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段后,就誤認(rèn)為是client再次發(fā)出的一個新的連接請求。于是就向client發(fā)出確認(rèn)報文段,同意建立連接。假設(shè)不采用“三次握手”,那么只要server發(fā)出確認(rèn),新的連接就建立了。由于現(xiàn)在client并沒有發(fā)出建立連接的請求,因此不會理睬server的確認(rèn),也不會向server發(fā)送數(shù)據(jù)。但server卻以為新的運輸連接已經(jīng)建立,并一直等待client發(fā)來數(shù)據(jù)。這樣,server的很多資源就白白浪費掉了。采用“三次握手”的辦法可以防止上述現(xiàn)象發(fā)生。例如剛才那種情況,client不會向server的確認(rèn)發(fā)出確認(rèn)。server由于收不到確認(rèn),就知道client并沒有要求建立連接?!?/p>
這就很明白了,防止了服務(wù)器端的一直等待而浪費資源。
什么要四次握手
TCP是全雙工模式,這就意味著:
- 當(dāng)主機1發(fā)出FIN報文段時,只是表示主機1已經(jīng)沒有數(shù)據(jù)要發(fā)送了,主機1告訴主機2,它的數(shù)據(jù)已經(jīng)全部發(fā)送完畢了;但是,這個時候主機1還是可以接受來自主機2的數(shù)據(jù);
- 當(dāng)主機2返回ACK報文段時,表示它已經(jīng)知道主機1沒有數(shù)據(jù)發(fā)送了,但是主機2還是可以發(fā)送數(shù)據(jù)到主機1的;
- 當(dāng)主機2也發(fā)送了FIN報文段時,這個時候就表示主機2也沒有數(shù)據(jù)要發(fā)送了,就會告訴主機1,我也沒有數(shù)據(jù)要發(fā)送了,之后彼此就會愉快的中斷這次TCP連接。