TCP連接的關(guān)閉方式
建立TCP連接需要三次握手,而關(guān)閉連接則需要四次握手,并且分為主動關(guān)閉和被動關(guān)閉。這是由于TCP連接是全雙工的,我關(guān)了你的連接,并不等于你關(guān)了我 的連接,因此雙方都必須單獨(dú)進(jìn)行關(guān)閉。當(dāng)一方完成它的數(shù)據(jù)發(fā)送任務(wù)后可以發(fā)送FIN包來終止這個方向的連接,表明自己不再有數(shù)據(jù)需要發(fā)送;收到FIN包的 那一方雖然不能再讀取數(shù)據(jù),但仍能發(fā)送數(shù)據(jù)。以Client主動關(guān)閉連接為例:
Client向Server發(fā)送FIN包,表示Client主動關(guān)閉連接,然后進(jìn)入FIN_WAIT_1狀態(tài),等待Server返回ACK包。此后Client不能再向Server發(fā)送數(shù)據(jù),但能讀取數(shù)據(jù)。
Server收到FIN包后向Client發(fā)送ACK包,然后進(jìn)入CLOSE_WAIT狀態(tài),此后Server不能再讀取數(shù)據(jù),但可以繼續(xù)向Client 發(fā)送數(shù)據(jù)。Client收到Server返回的ACK包后進(jìn)入FIN_WAIT_2狀態(tài),等待Server發(fā)送FIN包。
Server完成數(shù)據(jù)的發(fā)送后,將FIN包發(fā)送給Client,然后進(jìn)入LAST_ACK狀態(tài),等待Client返回ACK包,此后Server既不能讀取數(shù)據(jù),也不能發(fā)送數(shù)據(jù)。
Client收到FIN包后向Server發(fā)送ACK包,然后進(jìn)入TIME_WAIT狀態(tài),接著等待足夠長的時間(2MSL)以確保Server接收到 ACK包,最后回到CLOSED狀態(tài),釋放網(wǎng)絡(luò)資源。Server收到Client返回的ACK包后便回到CLOSED狀態(tài),釋放網(wǎng)絡(luò)資源。
TCP連接的建立到關(guān)閉,需要經(jīng)歷以下狀態(tài)遷移(假定Client發(fā)起連接,并主動關(guān)閉連接):
Client CLOSED -> SYN_SENT -> ESTABLISHED -> FIN_WAIT_1 -> FIN_WAIT_2 -> TIME_WAIT -> CLOSED
Server CLODES -> LISTEN -> SYN_RECEIVED -> ESTABLISHED -> CLOSE_WAIT -> LAST_ACK -> CLOSED
3. 對Server與Client的影響
在詳細(xì)了解TCP連接的狀態(tài)和關(guān)閉方式后,我們會發(fā)現(xiàn)TIME_WAIT狀態(tài)是一個坑爹的存在!主動關(guān)閉連接的一方在發(fā)送最后一個ACK包后,無論對方是 否收到都會進(jìn)入TIME_WAIT狀態(tài),等待2MSL的時間,然后才能釋放網(wǎng)絡(luò)資源。MSL就是Maximum Segment Lifetime(數(shù)據(jù)包的最大生命周期),是一個數(shù)據(jù)包能在互聯(lián)網(wǎng)上生存的最長時間,若超過這個時間則該數(shù)據(jù)包將會消失在網(wǎng)絡(luò)中。操作系統(tǒng)通常會將2MSL設(shè)為4分鐘,最低不少于30秒,因而TIME_WAIT狀態(tài)一般維持在30秒至4分鐘。這個是TCP/IP協(xié)議必不可少的,是TCP/IP設(shè)計者設(shè)計的,也就是無法解決的。TIME_WAIT狀態(tài)的存在主要有兩個原因:
可靠地實(shí)現(xiàn)TCP全雙工連接的終止。在關(guān)TCP閉連接時,最后的ACK包是由主動關(guān)閉方發(fā)出的,如果這個ACK包丟失,則被動關(guān)閉方將重發(fā)FIN包,因此 主動方必須維護(hù)狀態(tài)信息,以允許它重發(fā)這個ACK包。如果不維持這個狀態(tài)信息,那么主動方將回到CLOSED狀態(tài),并對被動方重發(fā)的FIN包響應(yīng)RST 包,而被動關(guān)閉方將此包解釋成一個錯誤(在Java中會拋出connection reset的SocketException)。因而,要實(shí)現(xiàn)TCP全雙工連接的正常終止,必須能夠處理四次握手協(xié)議中任意一個包丟失的情況,主動關(guān)閉方必須維持狀態(tài)信息進(jìn)入TIME_WAIT狀態(tài)。
確保迷路重復(fù)數(shù)據(jù)包在網(wǎng)絡(luò)中消失,防止上一次連接中的包迷路后重新出現(xiàn),影響新連接。TCP數(shù)據(jù)包可能由于路由器 異常而迷路,在迷路期間,數(shù)據(jù)包發(fā)送方可能因超時而重發(fā)這個包,迷路的數(shù)據(jù)包在路由器恢復(fù)后也會被送到目的地,這個迷路的數(shù)據(jù)包就稱為Lost Duplicate.在關(guān)閉一個TCP連接后,如果馬上使用相同的IP地址和端口建立新的TCP連接,那么有可能出現(xiàn)前一個連接的迷路重復(fù)數(shù)據(jù)包在前一個 連接關(guān)閉后再次出現(xiàn),影響新建立的連接。為了避免這一情況,TCP協(xié)議不允許使用處于TIME_WAIT狀態(tài)的連接的IP和端口啟動一個新連接,只有經(jīng)過2MSL的時間,確保上一次連接中所有的迷路重復(fù)數(shù)據(jù)包都已消失在網(wǎng)絡(luò)中,才能安全地建立新連接。
(責(zé)任編輯:VEVB)
新聞熱點(diǎn)
疑難解答
圖片精選