(轉(zhuǎn))TCP為什么需要3次握手與4次揮手
1. 為什么需要“三次握手”
在謝希仁著《計算機網(wǎng)絡(luò)》第四版中講“三次握手”的目的是“為了防止已失效的連接請求報文段突然又傳送到了服務(wù)端伞梯,因而產(chǎn)生錯誤”银亲。在另一部經(jīng)典的《計算機網(wǎng)絡(luò)》一書中講“三次握手”的目的是為了解決“網(wǎng)絡(luò)中存在延遲的重復(fù)分組”的問題赏僧。這兩種不用的表述其實闡明的是同一個問題庭敦。
謝希仁版《計算機網(wǎng)絡(luò)》中的例子是這樣的匿情,“已失效的連接請求報文段”的產(chǎn)生在這樣一種情況下:client發(fā)出的第一個連接請求報文段并沒有丟失,而是在某個網(wǎng)絡(luò)結(jié)點長時間的滯留了信殊,以致延誤到連接釋放以后的某個時間才到達server炬称。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段后涡拘,就誤認為是client再次發(fā)出的一個新的連接請求玲躯。于是就向client發(fā)出確認報文段,同意建立連接鳄乏。假設(shè)不采用“三次握手”跷车,那么只要server發(fā)出確認,新的連接就建立了橱野。由于現(xiàn)在client并沒有發(fā)出建立連接的請求朽缴,因此不會理睬server的確認,也不會向server發(fā)送數(shù)據(jù)水援。但server卻以為新的運輸連接已經(jīng)建立不铆,并一直等待client發(fā)來數(shù)據(jù)。這樣裹唆,server的很多資源就白白浪費掉了。采用”三次握手”的辦法可以防止上述現(xiàn)象發(fā)生只洒。例如剛才那種情況许帐,client不會向server的確認發(fā)出確認。server由于收不到確認毕谴,就知道client并沒有要求建立連接成畦。主要目的防止server端一直等待,浪費資源涝开。
2. 為什么需要“四次揮手”
那可能有人會有疑問循帐,在tcp連接握手時為何ACK是和SYN一起發(fā)送,這里ACK卻沒有和FIN一起發(fā)送呢舀武。原因是因為tcp是全雙工模式拄养,接收到FIN時意味將沒有數(shù)據(jù)再發(fā)來,但是還是可以繼續(xù)發(fā)送數(shù)據(jù)银舱。
3. 握手瘪匿,揮手過程中各狀態(tài)介紹
3次握手過程狀態(tài)(可參考下圖)
** LISTEN:**這個也是非常容易理解的一個狀態(tài),表示服務(wù)器端的某個SOCKET處于監(jiān)聽狀態(tài)寻馏,可以接受連接了棋弥。
** SYN_SENT:**當客戶端SOCKET執(zhí)行CONNECT連接時,它首先發(fā)送SYN報文诚欠,因此也隨即它會進入到了SYN_SENT狀態(tài)顽染,并等待服務(wù)端的發(fā)送三次握手中的第2個報文漾岳。SYN_SENT狀態(tài)表示客戶端已發(fā)送SYN報文。(發(fā)送端)
SYN_RCVD: 這個狀態(tài)與SYN_SENT遙想呼應(yīng)這個狀態(tài)表示接受到了SYN報文粉寞,在正常情況下尼荆,這個狀態(tài)是服務(wù)器端的SOCKET在建立TCP連接時的三次握手會話過程中的一個中間狀態(tài),很短暫仁锯,基本上用netstat你是很難看到這種狀態(tài)的耀找,除非你特意寫了一個客戶端測試程序,故意將三次TCP握手過程中最后一個 ACK報文不予發(fā)送业崖。因此這種狀態(tài)時野芒,當收到客戶端的ACK報文后,它會進入到ESTABLISHED狀態(tài)双炕。(服務(wù)器端)
ESTABLISHED:這個容易理解了狞悲,表示連接已經(jīng)建立了。
TCP三次握手示意圖
4次揮手過程狀態(tài)(可參考下圖)
FIN_WAIT_1: 這個狀態(tài)要好好解釋一下妇斤,其實FIN_WAIT_1和FIN_WAIT_2狀態(tài)的真正含義都是表示等待對方的FIN報文摇锋。而這兩種狀態(tài)的區(qū)別是:FIN_WAIT_1狀態(tài)實際上是當SOCKET在ESTABLISHED狀態(tài)時,它想主動關(guān)閉連接站超,向?qū)Ψ桨l(fā)送了FIN報文荸恕,此時該SOCKET即進入到FIN_WAIT_1狀態(tài)。而當對方回應(yīng)ACK報文后死相,則進入到FIN_WAIT_2狀態(tài)融求,當然在實際的正常情況下,無論對方何種情況下算撮,都應(yīng)該馬上回應(yīng)ACK報文生宛,所以FIN_WAIT_1狀態(tài)一般是比較難見到的,而FIN_WAIT_2狀態(tài)還有時常嘲构瘢可以用netstat看到陷舅。(主動方)
FIN_WAIT_2:上面已經(jīng)詳細解釋了這種狀態(tài),實際上FIN_WAIT_2狀態(tài)下的SOCKET审洞,表示半連接莱睁,也即有一方要求close連接,但另外還告訴對方芒澜,我暫時還有點數(shù)據(jù)需要傳送給你(ACK信息)缩赛,稍后再關(guān)閉連接。(主動方)
TIME_WAIT:表示收到了對方的FIN報文撰糠,并發(fā)送出了ACK報文**酥馍,就等2MSL后即可回到CLOSED可用狀態(tài)了。如果FIN_WAIT_1狀態(tài)下阅酪,收到了對方同時帶FIN標志和ACK標志的報文時旨袒,可以直接進入到TIME_WAIT狀態(tài)汁针,而無須經(jīng)過FIN_WAIT_2狀態(tài)。(主動方)
CLOSING(比較少見): 這種狀態(tài)比較特殊砚尽,實際情況中應(yīng)該是很少見施无,屬于一種比較罕見的例外狀態(tài)。正常情況下必孤,當你發(fā)送FIN報文后猾骡,按理來說是應(yīng)該先收到(或同時收到)對方的 ACK報文,再收到對方的FIN報文敷搪。但是CLOSING狀態(tài)表示你發(fā)送FIN報文后兴想,并沒有收到對方的ACK報文,反而卻也收到了對方的FIN報文赡勘。什么情況下會出現(xiàn)此種情況呢嫂便?其實細想一下,也不難得出結(jié)論:那就是如果雙方幾乎在同時close一個SOCKET的話闸与,那么就出現(xiàn)了雙方同時發(fā)送FIN報文的情況毙替,也即會出現(xiàn)CLOSING狀態(tài),表示雙方都正在關(guān)閉SOCKET連接践樱。
CLOSE_WAIT:這種狀態(tài)的含義其實是表示在等待關(guān)閉厂画。怎么理解呢?當對方close一個SOCKET后發(fā)送FIN報文給自己拷邢,你系統(tǒng)毫無疑問地會回應(yīng)一個ACK報文給對方木羹,此時則進入到CLOSE_WAIT狀態(tài)。接下來呢解孙,實際上你真正需要考慮的事情是察看你是否還有數(shù)據(jù)發(fā)送給對方,如果沒有的話抛人,那么你也就可以 close這個SOCKET弛姜,發(fā)送FIN報文給對方,也即關(guān)閉連接妖枚。所以你在CLOSE_WAIT狀態(tài)下廷臼,需要完成的事情是等待你去關(guān)閉連接。(被動方)
LAST_ACK:這個狀態(tài)還是比較容易好理解的绝页,它是被動關(guān)閉一方在發(fā)送FIN報文后荠商,最后等待對方的ACK報文。當收到ACK報文后续誉,也即可以進入到CLOSED可用狀態(tài)了莱没。(被動方)
CLOSED:表示連接中斷。
TCP四次揮手示意圖