建立一個連接需要三次握手,而終止一個連接要經(jīng)過四次揮手。
這由TCP的半關(guān)閉造成的。所謂的半關(guān)閉,其實就是TCP提供了連接的一端在結(jié)束它的發(fā)送后還能接收來自另一端數(shù)據(jù)的能力。
TCP 的連接的拆除需要發(fā)送四個包,因此稱為四次揮手(Four-way handshake),客戶端或服務(wù)器均可主動發(fā)起揮手動作。
剛開始雙方都處于 ESTABLISHED 狀態(tài),假如是客戶端先發(fā)起關(guān)閉請求。
四次揮手的過程如下:
第一次揮手:客戶端發(fā)送一個 FIN 報文,報文中會指定一個序列號。此時客戶端處于 FIN_WAIT1 狀態(tài)。即發(fā)出連接釋放報文段(FIN=1,序號seq=u),并停止再發(fā)送數(shù)據(jù),主動關(guān)閉TCP連接,進入FIN_WAIT1(終止等待1)狀態(tài),等待服務(wù)端的確認。
第二次揮手:服務(wù)端收到 FIN 之后,會發(fā)送 ACK 報文,且把客戶端的序列號值 +1 作為 ACK 報文的序列號值,表明已經(jīng)收到客戶端的報文了,此時服務(wù)端處于 CLOSE_WAIT 狀態(tài)。即服務(wù)端收到連接釋放報文段后即發(fā)出確認報文段(ACK=1,確認號ack=u+1,序號seq=v),服務(wù)端進入CLOSE_WAIT(關(guān)閉等待)狀態(tài),此時的TCP處于半關(guān)閉狀態(tài),客戶端到服務(wù)端的連接釋放??蛻舳耸盏椒?wù)端的確認后,進入FIN_WAIT2(終止等待2)狀態(tài),等待服務(wù)端發(fā)出的連接釋放報文段。
第三次揮手:如果服務(wù)端也想斷開連接了,和客戶端的第一次揮手一樣,發(fā)給 FIN 報文,且指定一個序列號。此時服務(wù)端處于 LAST_ACK 的狀態(tài)。即服務(wù)端沒有要向客戶端發(fā)出的數(shù)據(jù),服務(wù)端發(fā)出連接釋放報文段(FIN=1,ACK=1,序號seq=w,確認號ack=u+1),服務(wù)端進入LAST_ACK(最后確認)狀態(tài),等待客戶端的確認。
第四次揮手:客戶端收到 FIN 之后,一樣發(fā)送一個 ACK 報文作為應(yīng)答,且把服務(wù)端的序列號值 +1 作為自己 ACK 報文的序列號值,此時客戶端處于 TIME_WAIT 狀態(tài)。需要過一陣子以確保服務(wù)端收到自己的 ACK 報文之后才會進入 CLOSED 狀態(tài),服務(wù)端收到 ACK 報文之后,就處于關(guān)閉連接了,處于 CLOSED 狀態(tài)。即客戶端收到服務(wù)端的連接釋放報文段后,對此發(fā)出確認報文段(ACK=1,seq=u+1,ack=w+1),客戶端進入TIME_WAIT(時間等待)狀態(tài)。此時TCP未釋放掉,需要經(jīng)過時間等待計時器設(shè)置的時間2MSL后,客戶端才進入CLOSED狀態(tài)。
收到一個FIN只意味著在這一方向上沒有數(shù)據(jù)流動。客戶端執(zhí)行主動關(guān)閉并進入TIME_WAIT是正常的,服務(wù)端通常執(zhí)行被動關(guān)閉,不會進入TIME_WAIT狀態(tài)。
在socket編程中,任何一方執(zhí)行close()操作即可產(chǎn)生揮手操作。