前言
TCP
的三次握手??建立連接和四次揮手??斷開連接缤谎,相信很多人都聽說(shuō)過(guò),也都看過(guò)相關(guān)的內(nèi)容褐着,本篇是為了記錄自己對(duì)與這兩種操作的理解坷澡。
在進(jìn)入正式內(nèi)容之前,先來(lái)看幾個(gè)符號(hào)的概念:
序列號(hào)
seq
: 用來(lái)標(biāo)記數(shù)據(jù)段的順序含蓉,TCP
把連接中發(fā)送的所有數(shù)據(jù)字節(jié)都編上一個(gè)序號(hào)频敛,第一個(gè)字節(jié)的編號(hào)由本地隨機(jī)產(chǎn)生镣陕;給字節(jié)編上序號(hào)后,就給每一個(gè)報(bào)文段指派一個(gè)序號(hào)姻政;序列號(hào)seq
就是這個(gè)報(bào)文段中的第一個(gè)字節(jié)的數(shù)據(jù)編號(hào)。確認(rèn)號(hào)
ack
: 期待收到對(duì)方下一個(gè)報(bào)文段的第一個(gè)數(shù)據(jù)字節(jié)的序號(hào)岂嗓;序列號(hào)表示報(bào)文段攜帶數(shù)據(jù)的第一個(gè)字節(jié)的編號(hào)汁展;而確認(rèn)號(hào)指的是期望接收到下一個(gè)字節(jié)的編號(hào);因此當(dāng)前報(bào)文段最后一個(gè)字節(jié)的編號(hào)+1即為確認(rèn)號(hào)厌殉。確認(rèn)
ACK
: 僅當(dāng)ACK=1
時(shí)食绿,確認(rèn)號(hào)字段才有效。ACK=0
時(shí)公罕,確認(rèn)號(hào)無(wú)效同步
SYN
: 連接建立時(shí)用于同步序號(hào)器紧。當(dāng)SYN=1
,ACK=0
時(shí)表示:這是一個(gè)連接請(qǐng)求報(bào)文段楼眷。若同意連接铲汪,則在響應(yīng)報(bào)文段中使得SYN=1
,ACK=1
罐柳。因此掌腰,SYN=1
表示這是一個(gè)連接請(qǐng)求,或連接接受報(bào)文张吉。SYN
這個(gè)標(biāo)志位只有在TCP
建產(chǎn)連接時(shí)才會(huì)被置1齿梁,握手完成后SYN
標(biāo)志位被置0。終止
FIN
: 用來(lái)釋放一個(gè)連接肮蛹。FIN=1
表示:此報(bào)文段的發(fā)送方的數(shù)據(jù)已經(jīng)發(fā)送完畢勺择,并要求釋放運(yùn)輸連接
三次握手
首先進(jìn)入一下情景:
我正在飯店里和朋友吃飯,喝的正嗨的時(shí)候伦忠,女朋友打電話過(guò)來(lái)省核,飯店里有很多人,環(huán)境原因聽不太清電話里的聲音:
我:能聽到我的聲音嗎昆码?
女:能聽到芳撒,大點(diǎn)聲,你能聽到我講話嗎未桥?
我:能聽到笔刹,
如此這般,才能保證雙方都能聽到聲音冬耿,才能繼續(xù)對(duì)話呀舌菜。
TCP
是面向連接的,無(wú)論哪一方向另一方發(fā)送數(shù)據(jù)之前亦镶,都必須先在雙方之間建立一條連接日月。在TCP/IP
協(xié)議中袱瓮,TCP
協(xié)議提供可靠的連接服務(wù),連接是通過(guò)三次握手??進(jìn)行初始化的爱咬。三次握手??的目的是同步連接雙方的序列號(hào)和確認(rèn)號(hào)并交換 TCP
窗口大小信息尺借。由此我們來(lái)對(duì)應(yīng)客戶端與服務(wù)器之間的建立連接:
-
第一次握手??: 客戶端向服務(wù)器發(fā)出連接請(qǐng)求報(bào)文,這時(shí)報(bào)文首部中的同部位
SYN=1
精拟,同時(shí)隨機(jī)生成初始序列號(hào)seq=x
燎斩,此時(shí),客戶端進(jìn)程進(jìn)入了SYN-SENT
狀態(tài)蜂绎,等待服務(wù)器的確認(rèn)栅表。 -
第二次握手??: 服務(wù)器收到請(qǐng)求報(bào)文后,如果同意連接师枣,則發(fā)出確認(rèn)報(bào)文怪瓶。確認(rèn)報(bào)文中應(yīng)該
ACK=1
,SYN=1
践美,確認(rèn)號(hào)是ack=x+1
洗贰,同時(shí)也要為自己隨機(jī)初始化一個(gè)序列號(hào)seq=y
,此時(shí)陨倡,服務(wù)器進(jìn)程進(jìn)入了SYN-RCVD
狀態(tài)哆姻,詢問客戶端是否做好準(zhǔn)備。 -
第三次握手??: 客戶端進(jìn)程收到確認(rèn)后玫膀,還要向服務(wù)器給出確認(rèn)矛缨。確認(rèn)報(bào)文的
ACK=1
,ack=y+1
帖旨,此時(shí)箕昭,連接建立,客戶端進(jìn)入ESTABLISHED
狀態(tài)解阅,服務(wù)器端也進(jìn)入ESTABLISHED
狀態(tài)落竹。
以上就是三次握手??的一個(gè)大概流程,那么問題來(lái)了:
握手??為什么需要三次呢货抄,如果把最后一次的去掉改為兩次握手??是否可行呢?
假如現(xiàn)在客戶端想向服務(wù)端進(jìn)行握手述召,它發(fā)送了第一個(gè)連接的請(qǐng)求報(bào)文,但是由于網(wǎng)絡(luò)信號(hào)差或者服務(wù)器負(fù)載過(guò)多蟹地,這個(gè)請(qǐng)求沒有立即到達(dá)服務(wù)端积暖,而是在某個(gè)網(wǎng)絡(luò)節(jié)點(diǎn)中長(zhǎng)時(shí)間的滯留了,以至于滯留到客戶端連接釋放以后的某個(gè)時(shí)間點(diǎn)才到達(dá)服務(wù)端怪与,那么這就是一個(gè)失效的報(bào)文夺刑,但是服務(wù)端接收到這個(gè)失效的請(qǐng)求報(bào)文后,就誤認(rèn)為客戶端又發(fā)了一次連接請(qǐng)求,服務(wù)端就會(huì)想向客戶端發(fā)出確認(rèn)的報(bào)文遍愿,表示同意建立連接存淫。
假如不采用三次握手,那么只要服務(wù)端發(fā)出確認(rèn)沼填,表示新的建立就連接了桅咆。但是現(xiàn)在客戶端并沒有發(fā)出建立連接的請(qǐng)求,其實(shí)這個(gè)請(qǐng)求是失效的請(qǐng)求坞笙,一切都是服務(wù)端在自相情愿岩饼,因此客戶端是不會(huì)理睬服務(wù)端的確認(rèn)信息,也不會(huì)向服務(wù)端發(fā)送確認(rèn)的請(qǐng)求羞海,但是服務(wù)器卻認(rèn)為新的連接已經(jīng)建立起來(lái)了,并一直等待客戶端發(fā)來(lái)數(shù)據(jù)曲管,這樣的情況下却邓,服務(wù)端的很多資源就沒白白浪費(fèi)掉了。
采用三次握手的辦法就是為了防止上述這種情況的發(fā)生院水,比如就在剛才的情況下腊徙,客戶端不會(huì)向服務(wù)端發(fā)出確認(rèn)的請(qǐng)求,服務(wù)端會(huì)因?yàn)槭詹坏酱_認(rèn)的報(bào)文檬某,就知道客戶端并沒有要建立連接撬腾,那么服務(wù)端也就不會(huì)去建立連接,這就是三次握手的作用恢恼。
四次揮手
來(lái)民傻,再次進(jìn)入以下情景:
假如有一天我想要自由了,我就跟我的女朋友提出分手的要求:
我:我要自由场斑,自由萬(wàn)歲漓踢,分手吧
女:好,你要分手是吧
然后她會(huì)罵我渣啊來(lái)發(fā)泄漏隐,或者試圖挽留喧半,在經(jīng)過(guò)冷靜之后:
女:那就這樣吧,分
我:好的青责,分
至此就各奔東西挺据,互相安好,相忘于江湖脖隶。
當(dāng)客戶端和服務(wù)器通過(guò)三次握手建立了TCP
連接以后扁耐,當(dāng)數(shù)據(jù)傳送完畢,為了防止資源浪費(fèi)肯定要斷開TCP
連接产阱,那對(duì)于TCP
的斷開連接做葵,這里就有了斷開連接的四次揮手。
-
第一次揮手??: 客戶端進(jìn)程發(fā)出連接釋放FIN報(bào)文心墅,并且停止發(fā)送數(shù)據(jù)酿矢。釋放數(shù)據(jù)報(bào)文首部榨乎,
FIN=1
,其序列號(hào)為seq=x
,此時(shí)瘫筐,客戶端進(jìn)入FIN-WAIT-1
(終止等待1)狀態(tài)蜜暑。 -
第二次揮手??: 服務(wù)端進(jìn)程收到連接釋放
FIN
報(bào)文,發(fā)出確認(rèn)ACK
報(bào)文策肝,ACK=1
肛捍,ack=x+1
,并且?guī)献约旱男蛄刑?hào)seq=y
之众,此時(shí)拙毫,服務(wù)端就進(jìn)入了CLOSE-WAIT
(關(guān)閉等待)狀態(tài)。此時(shí)棺禾,服務(wù)端通知高層的應(yīng)用進(jìn)程缀蹄,客戶端向服務(wù)端的方向就釋放了,這時(shí)候處于半關(guān)閉狀態(tài)膘婶,即客戶端已經(jīng)沒有數(shù)據(jù)要發(fā)送了缺前,但是服務(wù)端若發(fā)送數(shù)據(jù),客戶端依然要接受悬襟。這個(gè)狀態(tài)還要持續(xù)一段時(shí)間衅码,也就是整個(gè)CLOSE-WAIT
狀態(tài)持續(xù)的時(shí)間〖乖溃客戶端收到服務(wù)端的確認(rèn)請(qǐng)求后逝段,此時(shí),客戶端就進(jìn)入FIN-WAIT-2
(終止等待2)狀態(tài)割捅,等待服務(wù)器發(fā)送連接釋放報(bào)文惹恃,在這之前依然可以接收服務(wù)端發(fā)送過(guò)來(lái)的最后的數(shù)據(jù)。 -
第三次揮手??: 服務(wù)端將最后的數(shù)據(jù)發(fā)送給客戶端完成后棺牧,就向客戶端發(fā)送連接釋放
FIN
報(bào)文巫糙,FIN=1
,ack=x+1
颊乘,此時(shí)的序列號(hào)為seq=z
参淹,此時(shí),服務(wù)端就進(jìn)入了LAST-ACK
(最后確認(rèn))狀態(tài)乏悄,等待客戶端的確認(rèn)浙值。 -
第四次揮手??: 客戶端接收到服務(wù)端的連接釋放
FIN
報(bào)文后,必須發(fā)出確認(rèn)報(bào)文檩小,ACK=1
开呐,ack=z+1
,而自己的序列號(hào)是seq=x+1
,此時(shí)筐付,客戶端就進(jìn)入了TIME-WAIT
(時(shí)間等待)狀態(tài)卵惦。此時(shí)服務(wù)端收到客戶端發(fā)送過(guò)來(lái)的確認(rèn)報(bào)文,就立即撤銷自己的傳輸控制塊TCB
,進(jìn)入CLOSED
狀態(tài)瓦戚,注意此時(shí)的TCP
連接還沒有釋放沮尿,必須經(jīng)過(guò)2MSL
(最長(zhǎng)報(bào)文段壽命)的時(shí)間后,客戶端沒有收到服務(wù)端發(fā)來(lái)的任何數(shù)據(jù)较解,證明服務(wù)端已正常關(guān)閉畜疾,此時(shí)客戶端會(huì)撤銷相應(yīng)傳輸控制塊TCB
后,進(jìn)入CLOSED
狀態(tài)印衔。至此啡捶,TCP
的連接才真正的斷開了。(服務(wù)端結(jié)束TCP
連接的時(shí)間要比客戶端稍微早一些)
好的奸焙,那么問題又來(lái)了:
為什么斷開連接需要四次揮手??呢瞎暑,像建立連接的時(shí)候一樣,三次行不行呢忿偷?
TCP
協(xié)議是一種面向連接的金顿、可靠的臊泌、基于字節(jié)流的運(yùn)輸層通信協(xié)議鲤桥。TCP
是全雙工 模式,這就意味著渠概,在客戶端想要斷開連接時(shí)茶凳,客戶端向服務(wù)端發(fā)送FIN
報(bào)文,只是表示客戶端已經(jīng)沒有數(shù)據(jù)要發(fā)送了播揪,但是這個(gè)時(shí)候客戶端還是可以接收來(lái)自服務(wù)端的數(shù)據(jù)贮喧。
當(dāng)服務(wù)端接收到FIN
報(bào)文,并返回ACK
報(bào)文猪狈,表示服務(wù)端已經(jīng)知道了客戶端要斷開連接箱沦,客戶端已經(jīng)沒有數(shù)據(jù)要發(fā)送了,但是這個(gè)時(shí)候服務(wù)端可能依然有數(shù)據(jù)要傳輸給客戶端雇庙。
當(dāng)服務(wù)端的數(shù)據(jù)傳輸完之后谓形,服務(wù)端會(huì)發(fā)送FIN
報(bào)文給客戶端,表示服務(wù)端也沒有數(shù)據(jù)要傳輸了疆前,服務(wù)端同意關(guān)閉連接寒跳,之后,客戶端收到FIN
報(bào)文竹椒,立即發(fā)送給客戶端一個(gè)ACK
報(bào)文童太,確定關(guān)閉連接。在之后,客戶端和服務(wù)端彼此就愉快的斷開了這次的TCP
連接书释。
或許會(huì)有疑問翘贮,為什么服務(wù)端的ACK
報(bào)文和FIN
報(bào)文都是分開發(fā)送的,但是在三次握手的時(shí)候卻是ACK
報(bào)文和SYN
報(bào)文是一起發(fā)送的征冷,因?yàn)樵谌挝帐值倪^(guò)程中择膝,當(dāng)服務(wù)端收到客戶端的SYN
連接請(qǐng)求報(bào)文后,可以直接發(fā)送SYN+ACK
報(bào)文检激。其中ACK
報(bào)文是用來(lái)應(yīng)答的肴捉,SYN
報(bào)文是用來(lái)同步的。但是在關(guān)閉連接時(shí)叔收,當(dāng)服務(wù)端接收到FIN
報(bào)文時(shí)齿穗,很可能并不會(huì)立即關(guān)閉SOCKET
,所以只能先回復(fù)一個(gè)ACK
報(bào)文饺律,告訴客戶端窃页,你發(fā)的FIN
報(bào)文我收到了,只有等到服務(wù)端所有的數(shù)據(jù)都發(fā)送完了复濒,才能發(fā)送FIN
報(bào)文脖卖,因此ACK
報(bào)文和FIN
報(bào)文不能一起發(fā)送。所以斷開連接的時(shí)候才需要四次揮手來(lái)完成巧颈。
驗(yàn)證
下面通過(guò)Wireshark
抓包工具來(lái)抓包看一下三次握手和四次揮手:
工具:Wireshark
下載地址 http://www.pc6.com/mac/112232.html
安裝完成之后畦木,打開Wireshark
,開始監(jiān)測(cè)網(wǎng)絡(luò)封包砸泛。
打開兩個(gè)終端窗口十籍,建立一個(gè)連接(這里很簡(jiǎn)單,就不截圖了):
在終端窗口1中唇礁,輸入:nc -l 6060
回車
在終端窗口2中勾栗,輸入:nc 127.0.0.1 6060
回車
兩個(gè)終端建立連接之后,可以在Wireshark
中看到三次握手的過(guò)程:
下面斷開連接再來(lái)看一下四次揮手的過(guò)程:
如果對(duì)照前面的三次握手和四次揮手的過(guò)程圖來(lái)看的話盏筐,更能明白此處的抓包到的數(shù)據(jù)围俘。
總結(jié)
TCP
的三次握手和四次揮手,個(gè)人覺得其實(shí)就是在建立連接和斷開連接的時(shí)候琢融,保證這個(gè)連接的“安全完整”界牡。同時(shí)也保證了數(shù)據(jù)的完整發(fā)送。至此關(guān)于TCP
的三次握手和四次揮手就寫到這里吏奸,如有錯(cuò)誤還請(qǐng)指正欢揖!
以上情景劇內(nèi)容純屬虛構(gòu),畢竟奋蔚,真正的車手是不需女人的她混。(滑稽保命)