連接
簡要過程
A:發(fā)送SYN請求 告訴B "我要連接了"
B:SYN演训、ACK ack = x+1贝咙,告訴A "哦 我知道了,你能聽到我的話"
A:ACK 告訴B "可以聽到庭猩!我要發(fā)數(shù)據(jù)了!震糖!"
A在發(fā)送ACK后趴腋,進入ESTABLISHED吊说,B在接受到ACK后進入ESTABLISHED
為什么這樣設計
保持通信雙方的信息對稱首昔,使通信雙方處于同步狀態(tài)
保證雙方都能發(fā)數(shù)據(jù)孝情,也能收數(shù)據(jù)民逼。如果當初的TCP設計的是兩次握手秀又,
- A發(fā)送SYN贬芥,B接收到 返回對A請求的確認,自身進入ESTABLISHED狀態(tài)蘸劈,A收到,進入ESTABLISHED (ok)
- A發(fā)送SYN贤惯,B接收到 返回對A請求的確認,自身進入ESTABLISHED狀態(tài)孵构,[SYN ACK]由于網(wǎng)絡原因,而停滯蜡镶。A以為SYN發(fā)送失敗恤筛,則重傳一個SYN,此時B再返回[SYN ACK]望伦,A收到煎殷,雙方都進入ESTABLISHED ,進行傳輸數(shù)據(jù)蝌数。假設此連接在通信結束后度秘,釋放連接資源,而此時第一次在網(wǎng)絡停滯但未被丟棄的SYN包抵達了唆貌,B又進入ESTABLISHED垢乙,而此時A已經(jīng)CLOSE,B一直沒有釋放連接資源追逮,苦苦等待,因此浪費了資源骂倘。
假設四次握手的過程是這樣:
- A->B SYN
- B->A ACK
- B->A SYN
- A->B ACK
中間二三步可以合并一起巴席,B既確認A(表示能收),發(fā)ACK給B荧库,試試能不能發(fā),四次沒有必要分衫,三步就可以確保雙方的收發(fā),建立連接摇邦。
知乎上看到的:
三次握手這個說法不好屎勘,其實是雙方各一次握手,各一次確認概漱,其中一次握手和確認合并在一起
終止
簡要過程
- A主動關閉方瓤摧,B被動關閉方
- A放送[FIN] 一個中斷請求給B,"我要關閉啦U彰帧!悔常!"
- B收到FIN给赞,發(fā)送ACK,告訴A残邀,"我知道了你要關閉了柑蛇,你還需要等我下,可能還有要發(fā)送的數(shù)據(jù)"耻台,通知應用程序。
- A收到 進入FIN_WAIT_1
- B進入CLOSE_WAIT狀態(tài)(被動關閉)鼓蜒,已經(jīng)沒有要發(fā)送的工作了,發(fā)送一個[FIN ACK]都弹,"我沒什么要發(fā)的,可以關閉啦"
- A收到進入FIN_WAIT_2冯痢,此時也得發(fā)送一個ACK確認框杜,"收到了你的關閉請求",進入TIME_WAIT狀態(tài)振劳,等待一個2MSL時間
- B收到了ACK油狂,進入CLOSED,A在2MSL的時間段內(nèi)沒有收到FIN专筷,確保最后一次ACK發(fā)送到B,這下放心地關閉了
為什么要這樣設計
設置TIME_WAIT的原因
MSL就是maximum segment lifetime(最大分節(jié)生命期)磷蛹,這是一個IP數(shù)據(jù)包能在互聯(lián)網(wǎng)上生存的最長時間,超過這個時間將在網(wǎng)絡中消失庇勃。
假設最終的 ACK 丟失 莺葫, server 將重發(fā) FIN , client 必須維護 TCP 狀態(tài)信息以便可以重發(fā)最終的 ACK ,否則會發(fā)送RST 贸铜,結果 server 認為發(fā)生錯誤。
若要TCP可靠地終止連接的兩個方向 ( 全雙工關閉 ) 烤镐, client 必須進 TIME_WAIT狀態(tài)棍鳖。
現(xiàn)在我們考慮終止連接時的被動方發(fā)送了一個FIN碗旅,然后主動方回復了一個ACK镜悉,然而這個ACK可能會丟失,這會造成被動方重發(fā)FIN旧困,這個FIN可能會在互聯(lián)網(wǎng)上存活MSL稼锅。
如果沒有TIME_WAIT的話,假設連接1已經(jīng)斷開矩距,然而其被動方最后重發(fā)的那個FIN(或者FIN之前發(fā)送的任何TCP分段)還在網(wǎng)絡上,然而連接2重用了連接1的所有的5元素(源IP锣咒,目的IP赞弥,TCP,源端口悼嫉,目的端口)拼窥,剛剛將建立好連接,連接1遲到的FIN到達了鲁纠,這個FIN將以比較低但是確實可能的概率終止掉連接2。
摘錄他人
摘自知乎的一段
作者:車小胖
鏈接:https://www.zhihu.com/question/67013338/answer/248375813
TCP四次揮手也遵循相似的套路情龄。
主動斷開的一側為A捍壤,被動斷開的一側為B。
- 第一個消息:A發(fā)FIN
- 第二個消息:B回復ACK
- 第三個消息:B發(fā)出FIN
此時此刻:B單方面認為自己與A達成了共識专酗,即雙方都同意關閉連接盗扇。此時沉填,B能釋放這個TCP連接占用的內(nèi)存資源嗎佑笋?不能,B一定要確保A收到自己的ACK橄碾、FIN颠锉。所以B需要靜靜地等待A的第四個消息的到來:
- 第四個消息:A發(fā)出ACK,用于確認收到B的FIN
當B接收到此消息琼掠,即認為雙方達成了同步:雙方都知道連接可以釋放了,此時B可以安全地釋放此TCP連接所占用的內(nèi)存資源悼瓮、端口號艰猬。
所以被動關閉的B無需任何wait time,直接釋放資源命贴。
但食听,A并不知道B是否接到自己的ACK,A是這么想的:
1)如果B沒有收到自己的ACK葬项,會超時重傳FiN那么A再次接到重傳的FIN迹蛤,會再次發(fā)送ACK
2)如果B收到自己的ACK,也不會再發(fā)任何消息笤受,包括ACK
無論是1還是2,A都需要等待,要取這兩種情況等待時間的最大值章喉,以應對最壞的情況發(fā)生,這個最壞情況是:
去向ACK消息最大存活時間(MSL) + 來向FIN消息的最大存活時間(MSL)落包。
這恰恰就是2MSL( Maximum Segment Life)。
等待2MSL時間涯鲁,A就可以放心地釋放TCP占用的資源有序、端口號,此時可以使用該端口號連接任何服務器警绩。
為何一定要等2MSL盅称?如果不等,釋放的端口可能會重連剛斷開的服務器端口缩膝,這樣依然存活在網(wǎng)絡里的老的TCP報文可能與新TCP連接報文沖突疾层,造成數(shù)據(jù)沖突,為避免此種情況云芦,需要耐心等待網(wǎng)絡老的TCP連接的活躍報文全部死翹翹,2MSL時間可以滿足這個需求(盡管非常保守)桌肴!