三次握手(three times handshake;three-way handshake)所謂的“三次握手”即對每次發(fā)送的數(shù)據(jù)量是怎樣跟蹤進(jìn)行協(xié)商使數(shù)據(jù)段的發(fā)送和接收同步,根據(jù)所接收到的數(shù)據(jù)量而確定的數(shù)據(jù)確認(rèn)數(shù)及數(shù)據(jù)發(fā)送、接收完畢后何時(shí)撤消聯(lián)系,并建立虛連接。
為了提供可靠的傳送,TCP在發(fā)送新的數(shù)據(jù)之前,以特定的順序?qū)?shù)據(jù)包的序號,并需要這些包傳送給目標(biāo)機(jī)之后的確認(rèn)消息。TCP總是用來發(fā)送大批量的數(shù)據(jù)。當(dāng)應(yīng)用程序在收到數(shù)據(jù)后要做出確認(rèn)時(shí)也要用到TCP。
四次揮手,別名連接終止協(xié)議。其性質(zhì)為終止協(xié)議。由于TCP連接是全雙工的,因此每個(gè)方向都必須單獨(dú)進(jìn)行關(guān)閉。這原則是當(dāng)一方完成它的數(shù)據(jù)發(fā)送任務(wù)后就能發(fā)送一個(gè)FIN來終止這個(gè)方向的連接。收到一個(gè) FIN只意味著這一方向上沒有數(shù)據(jù)流動,一個(gè)TCP連接在收到一個(gè)FIN后仍能發(fā)送數(shù)據(jù)。首先進(jìn)行關(guān)閉的一方將執(zhí)行主動關(guān)閉,而另一方執(zhí)行被動關(guān)閉。
建立TCP需要三次握手才能建立,而斷開連接則需要四次握手。整個(gè)過程如下圖所示:
先來看看如何建立連接的。
【更新于2017.01.04 】該部分內(nèi)容配圖有誤,請大家見諒,正確的配圖如下,錯(cuò)誤配圖也不刪了,大家可以比較下,對比理解效果更好。這么久才來更新,抱歉?。?/span>
錯(cuò)誤配圖如下:
首先Client端發(fā)送連接請求報(bào)文,Server段接受連接后回復(fù)ACK報(bào)文,并為這次連接分配資源。Client端接收到ACK報(bào)文后也向Server段發(fā)生ACK報(bào)文,并分配資源,這樣TCP連接就建立了。
那如何斷開連接呢?簡單的過程如下:
【注意】中斷連接端可以是Client端,也可以是Server端。
假設(shè)Client端發(fā)起中斷連接請求,也就是發(fā)送FIN報(bào)文。Server端接到FIN報(bào)文后,意思是說"我Client端沒有數(shù)據(jù)要發(fā)給你了",但是如果你還有數(shù)據(jù)沒有發(fā)送完成,則不必急著關(guān)閉Socket,可以繼續(xù)發(fā)送數(shù)據(jù)。所以你先發(fā)送ACK,"告訴Client端,你的請求我收到了,但是我還沒準(zhǔn)備好,請繼續(xù)你等我的消息"。這個(gè)時(shí)候Client端就進(jìn)入FIN_WAIT狀態(tài),繼續(xù)等待Server端的FIN報(bào)文。當(dāng)Server端確定數(shù)據(jù)已發(fā)送完成,則向Client端發(fā)送FIN報(bào)文,"告訴Client端,好了,我這邊數(shù)據(jù)發(fā)完了,準(zhǔn)備好關(guān)閉連接了"。Client端收到FIN報(bào)文后,"就知道可以關(guān)閉連接了,但是他還是不相信網(wǎng)絡(luò),怕Server端不知道要關(guān)閉,所以發(fā)送ACK后進(jìn)入TIME_WAIT狀態(tài),如果Server端沒有收到ACK則可以重傳。“,Server端收到ACK后,"就知道可以斷開連接了"。Client端等待了2MSL后依然沒有收到回復(fù),則證明Server端已正常關(guān)閉,那好,我Client端也可以關(guān)閉連接了。Ok,TCP連接就這樣關(guān)閉了!
整個(gè)過程Client端所經(jīng)歷的狀態(tài)如下:
而Server端所經(jīng)歷的過程如下:轉(zhuǎn)載請注明:blog.csdn.net/whuslei
【注意】 在TIME_WAIT狀態(tài)中,如果TCP client端最后一次發(fā)送的ACK丟失了,它將重新發(fā)送。TIME_WAIT狀態(tài)中所需要的時(shí)間是依賴于實(shí)現(xiàn)方法的。典型的值為30秒、1分鐘和2分鐘。等待之后連接正式關(guān)閉,并且所有的資源(包括端口號)都被釋放。
【問題1】為什么連接的時(shí)候是三次握手,關(guān)閉的時(shí)候卻是四次握手?
答:因?yàn)楫?dāng)Server端收到Client端的SYN連接請求報(bào)文后,可以直接發(fā)送SYN+ACK報(bào)文。其中ACK報(bào)文是用來應(yīng)答的,SYN報(bào)文是用來同步的。但是關(guān)閉連接時(shí),當(dāng)Server端收到FIN報(bào)文時(shí),很可能并不會立即關(guān)閉SOCKET,所以只能先回復(fù)一個(gè)ACK報(bào)文,告訴Client端,"你發(fā)的FIN報(bào)文我收到了"。只有等到我Server端所有的報(bào)文都發(fā)送完了,我才能發(fā)送FIN報(bào)文,因此不能一起發(fā)送。故需要四步握手。
【問題2】為什么TIME_WAIT狀態(tài)需要經(jīng)過2MSL(最大報(bào)文段生存時(shí)間)才能返回到CLOSE狀態(tài)?
答:雖然按道理,四個(gè)報(bào)文都發(fā)送完畢,我們可以直接進(jìn)入CLOSE狀態(tài)了,但是我們必須假象網(wǎng)絡(luò)是不可靠的,有可以最后一個(gè)ACK丟失。所以TIME_WAIT狀態(tài)就是用來重發(fā)可能丟失的ACK報(bào)文。
打個(gè)比方說:
TCP的握手,首先要明確的是必然有發(fā)起方(A)和接收方(B)。
第一次握手,必然是A向B發(fā)起的。即A向B發(fā)送了一個(gè)SYN包。如果套用高票的情境,可以理解為:"我想瞅瞅你,在嗎?"。
第二次握手,B發(fā)現(xiàn)有一個(gè)人試圖連接自己,那么就回復(fù)一個(gè)ACK包表示接收連接。即"在的,你瞅吧"。
第三次握手,是A在知道B同意讓自己連接后,也向B發(fā)一個(gè)ACK包表示我已經(jīng)就位。即"嗯,我已經(jīng)看到你了。(隱含著意思:我接下來要一直瞅你,如果兩個(gè)都沒說走,誰也不能走。)"
我看到好多答主在看到幾個(gè)回答后瞬間就進(jìn)入抖機(jī)靈模式,而且完全不管主被動的關(guān)系,也不管合理性,最后發(fā)展成看誰寫的三行短小說最好看了。
ps:高票的回答如果一定要三次握手的話,我覺得是這樣:
「 。。?!?--------------------漏了第一次握手
「你瞅啥?」 --------------------第二次握手
「瞅你咋地?」 --------------------第三次握手
「來咱倆嘮嘮。」 -------------------多余的交互
TCP是一個(gè)喪心病狂的追求效率的協(xié)議,除非必要,絕不會有多余的報(bào)文。
如對本文有疑問,請?zhí)峤坏浇涣髡搲瑥V大熱心網(wǎng)友會為你解答??! 點(diǎn)擊進(jìn)入論壇