三次握手與四次揮手是指TCP連接建立與釋放的過程膝迎。為了弄清楚三次握手和四次揮手捅儒,需要先簡單了解什么是TCP協(xié)議墨坚,TCP協(xié)議的特點(diǎn)以及TCP傳送的數(shù)據(jù)單元。
一凤类、什么是TCP協(xié)議
TCP穗泵,Transmission Control Protocol,中文名為傳輸控制協(xié)議谜疤。它屬于傳輸層通信協(xié)議佃延,是為了在不可靠的IP層上實現(xiàn)可靠傳輸?shù)臄?shù)據(jù)傳輸協(xié)議。網(wǎng)絡(luò)層雖然可以實現(xiàn)兩個主機(jī)之間的通信夷磕,但真正進(jìn)行通信的實體是在主機(jī)的進(jìn)程中履肃,而傳輸層位于網(wǎng)絡(luò)層之上,是它為運(yùn)行在不同主機(jī)的進(jìn)程之間提供了邏輯通信坐桩。傳輸層提供兩種不同的傳輸協(xié)議榆浓,即面向連接的TCP協(xié)議和無連接的UDP協(xié)議。
二撕攒、TCP協(xié)議的特點(diǎn)
1)面向連接陡鹃。
2)每個TCP連接只能有兩個端點(diǎn),即一對一抖坪。
3)TCP提供可靠的交付服務(wù)萍鲸,保證傳送的數(shù)據(jù)無差錯、不丟失擦俐、不重復(fù)且有序脊阴。
4)TCP提供全雙工通信,即允許通信雙方的應(yīng)用進(jìn)程在任何時候都能發(fā)送數(shù)據(jù)。
5)面向字節(jié)流嘿期,TCP把交付數(shù)據(jù)僅看作一連串無結(jié)構(gòu)的字節(jié)流品擎。
三、TCP報文段
TCP傳送的數(shù)據(jù)單元稱為報文段备徐,一個TCP報文段由首部和數(shù)據(jù)部分兩個部分組成萄传。TCP報文段既可以用來運(yùn)載數(shù)據(jù),也可以用來建立連接蜜猾、釋放連接和應(yīng)答秀菱。
其中幾個和連接相關(guān)的重要字段:
1)序號字段:用來給TCP連接中傳送的數(shù)據(jù)流編號。由于TCP是面向字節(jié)流的蹭睡,故規(guī)定序號字段的值指的是該報文段所發(fā)送的數(shù)據(jù)的第一個字節(jié)的編號衍菱。
2)確認(rèn)號字段:用來表示已確認(rèn)收到的數(shù)據(jù)。規(guī)定其值含義為期望收到對方的下一個報文段的數(shù)據(jù)部分的第一個字節(jié)的編號肩豁。比如確認(rèn)號為N脊串,表示到序號N-1為止的所有數(shù)據(jù)都已正確收到。
3)確認(rèn)位ACK:ACK=1表示這是對對方發(fā)送的報文段的確認(rèn)報文段清钥。
4)同步位SYN:同步位SYN=1表示這是一個連接請求或連接接收報文段琼锋。
5)終止位FIN:FIN=1表示已發(fā)送完畢的一方要釋放連接。
四循捺、三次握手過程
首先斩例,說明一下TCP兩端連接建立過程中的幾種狀態(tài):
1)CLOSED:表示初始狀態(tài)雄人。
2)LISTEN:表示服務(wù)器端的某個SOCKET處于監(jiān)聽狀態(tài)从橘,可以接受連接了。
3)SYN_SENT:當(dāng)客戶端SOCKET執(zhí)行CONNECT連接時础钠,它首先發(fā)送SYN報文恰力,因此也隨即它會進(jìn)入到了SYN_SENT狀態(tài),并等待服務(wù)端的發(fā)送三次握手中的第2個報文旗吁。
4)SYN_RCVD:表示收到了SYN報文踩萎,這種狀態(tài)時,當(dāng)收到客戶端的ACK報文后會進(jìn)入到ESTABLISHED狀態(tài)很钓。在正常情況下香府,這個狀態(tài)很短暫,基本上用netstat是很難看到的码倦,除非特意寫一個客戶端測試程序企孩,故意將三次握手中最后一個ACK報文不予發(fā)送。
5)ESTABLISHED:表示連接已經(jīng)建立了袁稽。
第一步:客戶機(jī)的TCP(指TCP傳輸實體)向服務(wù)器的TCP發(fā)送一個連接請求報文段勿璃。其首部中SYN=1(表示這是一個連接請求報文段)。另外,客戶機(jī)會選擇一個起始序號seq=x补疑,SYN報文不攜帶應(yīng)用層傳下來的數(shù)據(jù)歧沪,但要消耗掉一個序號。此時莲组,客戶端從CLOSED狀態(tài)進(jìn)入SYN_SENT狀態(tài)诊胞。
第二步:服務(wù)器的TCP收到連接請求報文段后,如果同意連接胁编,就向客戶機(jī)發(fā)回確認(rèn)厢钧,并為該TCP連接分配TCP緩存和變量。在該確認(rèn)報文段中嬉橙,SYN=1早直,ACK=1(表示這是一個連接接收報文段),且ack=x+1市框,服務(wù)器產(chǎn)生起始序號seq=y霞扬。同樣,該報文不攜帶應(yīng)用層傳下來的數(shù)據(jù)枫振,但也要消耗掉一個序號喻圃。此時,服務(wù)器端從LISTEN狀態(tài)進(jìn)入SYN_RCVD狀態(tài)粪滤。
【注】因為TCP是全雙工通信斧拍,所以TCP連接的兩端都各自設(shè)有發(fā)送緩存和接收緩存。發(fā)送緩存用來暫時存放以下數(shù)據(jù):(1)發(fā)送應(yīng)用程序傳送給發(fā)送方TCP準(zhǔn)備發(fā)送的數(shù)據(jù)杖小;(2)TCP已發(fā)送但尚未收到確認(rèn)的數(shù)據(jù)肆汹。接收緩存用來暫時存放以下數(shù)據(jù):(1)按序到達(dá)的但尚未被接受應(yīng)用程序讀取的數(shù)據(jù);(2)不按序到達(dá)的數(shù)據(jù)予权。
第三步:當(dāng)客戶機(jī)收到服務(wù)器的確認(rèn)報文段后昂勉,還要再次向服務(wù)器給出確認(rèn),并且給該連接分配緩存和變量扫腺。這個報文段的ACK=1岗照,SYN=0(只有前兩次握手才需要SYN=1),seq=x+1笆环,ack=y+1攒至。此報文段可以攜帶數(shù)據(jù)了,如果不攜帶數(shù)據(jù)則不消耗序號躁劣。此時迫吐,客戶端和服務(wù)器端進(jìn)入ESTABLISHED狀態(tài),連接建立完成习绢。
五渠抹、四次揮手過程
四次揮手指TCP連接釋放的過程蝙昙,由于TCP是全雙工通信,可以理解為一個TCP連接上有兩條數(shù)據(jù)通路梧却,所以需要TCP連接兩段分別斷開每一條數(shù)據(jù)通路奇颠。
TCP兩端連接釋放的幾種狀態(tài):
1)FIN_WAIT_1:當(dāng)客戶端在ESTABLISHED狀態(tài)想主動關(guān)閉連接時,向?qū)Ψ桨l(fā)送FIN報文即進(jìn)入到FIN_WAIT_1狀態(tài)放航。等對方回應(yīng)ACK報文后烈拒,則進(jìn)入到FIN_WAIT_2狀態(tài)。在實際正常情況下广鳍,無論對方何種情況荆几,都應(yīng)該馬上回應(yīng)ACK報文,故FIN_WAIT_1狀態(tài)一般是比較難見到的赊时,而FIN_WAIT_2狀態(tài)還有時常扯种可以用netstat看到。
2)FIN_WAIT_2:表示半連接祖秒,也就是只關(guān)閉了其中一條數(shù)據(jù)通路诞吱。
3)TIME_WAIT:表示收到了對方的FIN報文并發(fā)送出了ACK報文,只等2MSL后即可回到CLOSED狀態(tài)了竭缝。如果在FIN_WAIT_1狀態(tài)下收到了對方同時帶FIN標(biāo)志和ACK標(biāo)志的報文房维,可以直接進(jìn)入到TIME_WAIT狀態(tài),而無須經(jīng)過FIN_WAIT_2狀態(tài)抬纸。
4)CLOSING:表示客戶端發(fā)送FIN報文后咙俩,并沒有收到對方的ACK報文,反而收到對方的FIN報文湿故,也就是通信雙方都正在關(guān)閉SOCKET連接阿趁。這種狀態(tài)實際情況中很罕見。
5)CLOSE_WAIT:當(dāng)收到對方發(fā)送的FIN報文并回應(yīng)一個ACK報文時則進(jìn)入到CLOSE_WAIT狀態(tài)晓锻。在CLOSE_WAIT狀態(tài)下歌焦,考慮自己是否還有數(shù)據(jù)要發(fā)送飞几。
6)LAST_ACK:表示被動關(guān)閉一方在發(fā)送FIN報文后砚哆,最后等待對方的ACK報文。當(dāng)收到ACK報文后屑墨,也即可以進(jìn)入到CLOSED可用狀態(tài)了躁锁。
第一步:當(dāng)客戶端數(shù)據(jù)發(fā)送完成準(zhǔn)備關(guān)閉連接時,就向其TCP傳輸實體發(fā)送一個連接釋放報文段卵史,主動關(guān)閉TCP連接战转,該報文段FIN=1,seq=u(前面已傳送的數(shù)據(jù)的最后的一個字節(jié)的序號加1)以躯,和SYN報文段一樣槐秧,F(xiàn)IN報文段即使不攜帶數(shù)據(jù)啄踊,也要消耗掉一個序號,其實應(yīng)該還有一個ack=v(圖上沒標(biāo)刁标,因為不是重點(diǎn))颠通。當(dāng)一端發(fā)送FIN報文時,它就不能再發(fā)送數(shù)據(jù)膀懈,相當(dāng)于這關(guān)閉了其中一條數(shù)據(jù)通路顿锰,而另一端可以繼續(xù)發(fā)送數(shù)據(jù)。此時启搂,客戶端進(jìn)入FIN-WAIT-1狀態(tài)硼控。
第二步:服務(wù)器收到連接釋放報文段后即發(fā)出確認(rèn),ack=u+1胳赌,seq=v牢撼,等于它前面已傳送過的數(shù)據(jù)的最后一個字節(jié)的序號加1。此時疑苫,從客戶機(jī)到服務(wù)器這個方向的連接就算釋放了浪默,TCP連接處于半關(guān)閉狀態(tài)。但從服務(wù)器到客戶機(jī)這個方向的數(shù)據(jù)通路并未關(guān)閉缀匕。此時纳决,服務(wù)端就進(jìn)入了CLOSE-WAIT狀態(tài),而當(dāng)客戶端收到了服務(wù)器端的確認(rèn)報文段后即進(jìn)入FIN-WAIT-2狀態(tài)乡小。
第三步:若服務(wù)器發(fā)送完畢阔加,就通知TCP釋放連接,此時發(fā)出FIN=1的連接釋放報文段满钟。ACK=1胜榔,ack=u+1,seq=w湃番。此時夭织,服務(wù)器就進(jìn)入了LAST-ACK狀態(tài)。
第四步:客戶機(jī)收到連接釋放報文段后吠撮,必須發(fā)出確認(rèn)尊惰。此時,客戶端就進(jìn)入了TIME-WAIT狀態(tài)泥兰。在確認(rèn)報文段中弄屡,ACK=1,ack=w+1鞋诗,seq=u+1膀捷。但這時TCP連接還沒釋放掉,必須經(jīng)過時間等待計時器設(shè)置的時間2MSL后削彬,客戶端和服務(wù)器端都進(jìn)入CLOSED狀態(tài)全庸。
六秀仲、相關(guān)問題
1)為什么不能用兩次握手進(jìn)行TCP連接?
答:主要防止已經(jīng)失效的連接請求報文突然又傳送到了服務(wù)器壶笼,從而產(chǎn)生錯誤啄育。在采取兩次握手的情況下,假設(shè)客戶端發(fā)送了第一個請求連接并且沒有丟失拌消,只是在網(wǎng)絡(luò)結(jié)點(diǎn)中滯留的時間太長了挑豌,由于客戶端遲遲沒有收到確認(rèn)報文,以為服務(wù)器沒有收到墩崩,便重新向服務(wù)器發(fā)送連接請求報文氓英,此后客戶端和服務(wù)器經(jīng)過兩次握手完成連接,傳輸數(shù)據(jù)鹦筹,然后關(guān)閉連接铝阐。但之前滯留的那條連接請求報文,又網(wǎng)絡(luò)通暢了铐拐,到達(dá)了服務(wù)器徘键,這個報文本該是失效的,但是遍蟋,兩次握手的機(jī)制將會讓客戶端和服務(wù)器再次建立連接吹害,這將導(dǎo)致不必要的錯誤和資源的浪費(fèi)。如果采用的是三次握手虚青,當(dāng)之前失效的連接請求報文傳送過來時它呀,就算服務(wù)器端回復(fù)了確認(rèn)報文,但是客戶端不會再次發(fā)出確認(rèn)棒厘,就不會建立連接纵穿。
2)為什么連接的時候是三次握手,關(guān)閉的時候卻是四次揮手奢人?
答:連接時谓媒,當(dāng)服務(wù)器端收到客戶端的SYN報文后,可以直接發(fā)送SYN+ACK報文何乎,也就是應(yīng)答加上同步句惯。但是關(guān)閉連接時,當(dāng)服務(wù)器端收到FIN報文時宪赶,很可能還要繼續(xù)向客戶端發(fā)送數(shù)據(jù)宗弯,所以只能先回復(fù)一個ACK報文脯燃。只有服務(wù)器端所有的報文都發(fā)送完了搂妻,才能向客戶端發(fā)送FIN報文,因此不能一起發(fā)送辕棚。故需要四次揮手欲主。
3)為什么TIME_WAIT狀態(tài)需要經(jīng)過2MSL(Maximum Segment Lifetime邓厕,最大報文段生存時間)才能返回到CLOSE狀態(tài)?
答:為了保證最后一個ACK能夠順利到達(dá)扁瓢。MSL指一個片段在網(wǎng)絡(luò)中最大的存活時間详恼,2MSL就是一個發(fā)送和一個回復(fù)所需的最大時間。如果不等待2MSL引几,且最后一個ACK丟失昧互,則服務(wù)器端不能進(jìn)入正常關(guān)閉狀態(tài),造成錯誤伟桅。所以TIME_WAIT狀態(tài)就是用來重發(fā)可能丟失的ACK報文敞掘。如果Server沒有收到ACK,將不斷重復(fù)發(fā)送FIN報文段楣铁。Client在發(fā)送出ACK之后進(jìn)入到TIME_WAIT狀態(tài)并且設(shè)置一個計時器玖雁,等待2MSL的時間。如果在2MSL時間內(nèi)再次收到FIN盖腕,說明最后一個ACK丟失赫冬,那么Client會重發(fā)ACK并再次等待2MSL。如果直到2MSL溃列,Client都沒有再次收到FIN劲厌,那么Client推斷ACK已經(jīng)被成功接收,則成功結(jié)束TCP連接听隐。(服務(wù)器結(jié)束TCP連接的時間要比客戶端早一些脊僚,因為客戶端最后要等待2MSL后才可以進(jìn)入CLOSED狀態(tài)。)
4)如果已經(jīng)建立了連接遵绰,但是客戶端突然出現(xiàn)故障了怎么辦辽幌?
答:TCP還設(shè)有一個保活計時器椿访,顯然乌企,客戶端如果出現(xiàn)故障,服務(wù)器不能一直等下去成玫,白白浪費(fèi)資源加酵。服務(wù)器每收到一次客戶端的請求后都會重新復(fù)位這個計時器,時間通常是設(shè)置為2小時,若兩小時還沒有收到客戶端的任何數(shù)據(jù)浪漠,服務(wù)器就會發(fā)送一個探測報文段烙肺,以后每隔75秒鐘發(fā)送一次。若一連發(fā)送10個探測報文仍然沒反應(yīng)陋葡,服務(wù)器就認(rèn)為客戶端出了故障,接著就關(guān)閉連接彻采。
4)為什么TCP在建立連接時不能每次都選擇相同的腐缤、固定的初始序號捌归?
答:假定每一次建立連接時,主機(jī)A都選擇相同的岭粤、固定的初始序號惜索,比如1。假設(shè)主機(jī)A和B頻繁地建立連接剃浇,且A發(fā)送的某些TCP報文段會在網(wǎng)絡(luò)中滯留較長的時間巾兆,以造成A超時重傳這些報文段。而有一些在網(wǎng)絡(luò)中滯留時間較長的報文段最后終于到達(dá)了主機(jī)B虎囚,但這時傳送該報文段的那個連接早已釋放了臼寄。這樣,工作在新的TCP連接中的主機(jī)B就有可能會接收在舊的連接中的溜宽、已經(jīng)沒有意義的吉拳、過時的報文段,結(jié)果產(chǎn)生錯誤适揉。
參考文檔:
(1)《王道2019年計算機(jī)網(wǎng)絡(luò)考研復(fù)習(xí)指導(dǎo)》留攒;
(2)TCP三次握手原理,以及為什么不能改成兩次握手 - 若水彈丸之地 - CSDN博客https://blog.csdn.net/b954960630/article/details/81861579嫉嘀;