1、TCP三次握手
TCP建立連接需要進(jìn)行“三次握手”:
TCP三次握手過程描述如下:
客戶端發(fā)送連接請(qǐng)求報(bào)文:SYN標(biāo)志位為1,ACK標(biāo)志位為0巍扛,序列號(hào)seq為x吠昭。然后客戶端進(jìn)入SYN_SENT狀態(tài),等待服務(wù)器的確認(rèn)響應(yīng)蒲肋;
服務(wù)器收到客戶端的連接請(qǐng)求,對(duì)這個(gè)SYN報(bào)文段進(jìn)行確認(rèn),發(fā)送:SYN標(biāo)志位為1距糖,ACK標(biāo)志位為1,序列號(hào)seq為y,確認(rèn)序列號(hào)ack為x+1浓领。此時(shí)服務(wù)器進(jìn)入SYN_RCVD狀態(tài);
客戶端收到服務(wù)器的SYN+ACK報(bào)文段,確認(rèn)ACK后祸泪,發(fā)送:SYN標(biāo)志位為0,ACK標(biāo)志位為1微王,序列號(hào)seq為x+1,確認(rèn)序列號(hào)ack為y+1罩旋。發(fā)送完成后,客戶端和服務(wù)器端都進(jìn)入ESTABLISHED狀態(tài)浴骂,完成TCP三次握手。
2、TCP四次揮手
TCP斷開連接需要進(jìn)行“四次揮手”:
TCP四次揮手過程描述如下:
主機(jī)1(可以使客戶端,也可以是服務(wù)器端)發(fā)送:FIN標(biāo)志位為1伊诵,ACK標(biāo)志位為0,序列號(hào)seq為u份氧。此時(shí)蜗帜,主機(jī)1進(jìn)入FIN_WAIT_1狀態(tài)宴偿。
主機(jī)2收到了主機(jī)1發(fā)送的FIN報(bào)文段窄刘,向主機(jī)1回一個(gè)ACK報(bào)文段:FIN標(biāo)志位為1,ACK標(biāo)志位為1,序列號(hào)seq為v沮焕,確認(rèn)序列號(hào)ack為u+1。主機(jī)1進(jìn)入FIN_WAIT_2狀態(tài)络它;主機(jī)2進(jìn)入CLOSE_WAIT狀態(tài)化戳。
主機(jī)2向主機(jī)1發(fā)送FIN報(bào)文段:FIN標(biāo)志位為1点楼,ACK標(biāo)志位為1掠廓,序列號(hào)seq為w蟀瞧,確認(rèn)序列號(hào)ack為u+1。請(qǐng)求關(guān)閉連接,同時(shí)主機(jī)2進(jìn)入LAST_ACK狀態(tài)踏枣。
主機(jī)1收到主機(jī)2發(fā)送的FIN報(bào)文段间驮,向主機(jī)2發(fā)送ACK報(bào)文段:FIN標(biāo)志位為1蜻牢,ACK標(biāo)志位為1,序列號(hào)seq為u+1抱虐,確認(rèn)序列號(hào)ack為w+1。谣沸,然后主機(jī)1進(jìn)入TIME_WAIT狀態(tài);主機(jī)2收到主機(jī)1的ACK報(bào)文段以后,就關(guān)閉連接举农;此時(shí),主機(jī)1等待2MSL后依然沒有收到回復(fù)棱貌,則證明Server端已正常關(guān)閉突雪,那么惹想,主機(jī)1也可以關(guān)閉連接了嘀粱。
3辰狡、狀態(tài)轉(zhuǎn)換圖
4宛篇、幾個(gè)問題
4.1 TCP中“全雙工的字節(jié)流”含義的理解叫倍!
(1)全雙工:
意味著,TCP的收發(fā)是可以同時(shí)進(jìn)行的听诸。也就是說收的時(shí)候可以發(fā)晌梨,發(fā)的時(shí)候也可以收赛糟,兩者互不沖突璧南。
(2)字節(jié):
意味著,無論物理層或鏈路層收到的數(shù)據(jù)是否為一個(gè)個(gè)bit的數(shù)據(jù)豆混,在TCP層一定是一個(gè)個(gè)字節(jié)皿伺。
(3)流:
意味著鸵鸥,socket的數(shù)據(jù)無頭無尾,就像流水一樣宋税,如果從中間任意位置起杰赛,你無法知道一個(gè)消息包確切的開始或結(jié)束位置矮台,除非從TCP的頭開始算起。也就是意味著辰晕,我們在應(yīng)用層編程時(shí)确虱,必須定義一個(gè)應(yīng)用層的包頭,從收到的第一個(gè)字節(jié)開始唱较,通過該包頭能確定一個(gè)包的長度南缓,然后根據(jù)包的長度荧呐,確定一個(gè)個(gè)包的起止位置倍阐。這也就是我們看到所有的TCP的socket編程中峰搪,都需要定義一個(gè)包頭的原因。
4.2 為什么是“三次握手”使套?
因?yàn)門CP是“全雙工通信”侦高。
前提1:TCP協(xié)議要保證雙方可以建立可靠的通信奉呛。 即 發(fā)送端、接收端要確認(rèn)自己發(fā)送的信息對(duì)方能接收到危尿,對(duì)方發(fā)送的信息自己能接收到。(必須確認(rèn)收罗晕、發(fā)正常)
前提2:在前提1的情況下“握手”的次數(shù)越少越好小渊。
(1)第一次握手
發(fā)送端向接受端發(fā)送一個(gè)SYN包茫叭。
發(fā)送端:無法確認(rèn)自己發(fā)送的信息對(duì)方是否收到揍愁。
(2)第二次握手
接收端收到SYN包之后,接收端回一個(gè)ACK包谬擦。
發(fā)送端:可以確定自己發(fā)送的信息能被對(duì)方收到惨远,也能確定對(duì)方發(fā)的信息自己能收到。
接收端:只能確定對(duì)方發(fā)的包自己能收到北秽, 無法確定自己發(fā)的包對(duì)方能收到贺氓。
(3)第三次握手
發(fā)送端接收到SYN掠归,之后再發(fā)一個(gè)ACK虏冻。
接收端:能夠確定字節(jié)發(fā)送的消息厨相,發(fā)送端能夠收到蛮穿。
4.3 三次握手建立連接時(shí)单刁,發(fā)送方再次發(fā)送確認(rèn)(第三次握手)的必要性?
主要是為了防止發(fā)送方已失效的連接請(qǐng)求報(bào)文段突然又傳到了B府适,因而產(chǎn)生錯(cuò)誤羔飞。假定出現(xiàn)一種異常情況,即A發(fā)出的第一個(gè)連接請(qǐng)求報(bào)文段并沒有丟失檐春,而是在某些網(wǎng)絡(luò)結(jié) 點(diǎn)長時(shí)間滯留了逻淌,一直延遲到連接釋放以后的某個(gè)時(shí)間才到達(dá)B,本來這是一個(gè)早已失效的報(bào)文段疟暖。但B收到此失效的連接請(qǐng)求報(bào)文段后卡儒,就誤認(rèn)為是A又發(fā)出一次 新的連接請(qǐng)求,于是就向A發(fā)出確認(rèn)報(bào)文段俐巴,同意建立連接骨望。假定不采用三次握手,那么只要B發(fā)出確認(rèn)欣舵,新的連接就建立了,這樣一直等待A發(fā)來數(shù)據(jù)糠亩,B的許多 資源就這樣白白浪費(fèi)了。
4.4 四次揮手釋放連接時(shí),等待2MSL的意義滞项?
原因有二:
(1)保證TCP協(xié)議的全雙工連接能夠可靠關(guān)閉。
(2)保證這次連接的重復(fù)數(shù)據(jù)段從網(wǎng)絡(luò)中消失疚宇。
先說第一點(diǎn),如果Client直接CLOSED了榜揖,那么由于IP協(xié)議的不可靠性或者是其它網(wǎng)絡(luò)原因物蝙,導(dǎo)致Server沒有收到Client最后回復(fù)的ACK钠导。那么Server就會(huì)在超時(shí)之后繼續(xù)發(fā)送FIN票堵,此時(shí)由于Client已經(jīng)CLOSED了,就找不到與重發(fā)的FIN對(duì)應(yīng)的連接,最后Server就會(huì)收到RST而不是ACK,Server就會(huì)以為是連接錯(cuò)誤把問題報(bào)告給高層。這樣的情況雖然不會(huì)造成數(shù)據(jù)丟失吗货,但是卻導(dǎo)致TCP協(xié)議不符合可靠連接的要求警检。所以窥摄,Client不是直接進(jìn)入CLOSED崭放,而是要保持TIME_WAIT,當(dāng)再次收到FIN的時(shí)候,能夠保證對(duì)方收到ACK边锁,最后正確的關(guān)閉連接则拷。
再說第二點(diǎn),如果Client直接CLOSED,然后又再向Server發(fā)起一個(gè)新連接笙纤,我們不能保證這個(gè)新連接與剛關(guān)閉的連接的端口號(hào)是不同的腥椒。也就是說有可能新連接和老連接的端口號(hào)是相同的洒放。一般來說不會(huì)發(fā)生什么問題惋戏,但是還是有特殊情況出現(xiàn):假設(shè)新連接和已經(jīng)關(guān)閉的老連接端口號(hào)是一樣的,如果前一次連接的某些數(shù)據(jù)仍然滯留在網(wǎng)絡(luò)中,這些延遲數(shù)據(jù)在建立新連接之后才到達(dá)Server欧漱,由于新連接和老連接的端口號(hào)是一樣的,又因?yàn)門CP協(xié)議判斷不同連接的依據(jù)是socket pair,于是郊丛,TCP協(xié)議就認(rèn)為那個(gè)延遲的數(shù)據(jù)是屬于新連接的揍瑟,這樣就和真正的新連接的數(shù)據(jù)包發(fā)生混淆了底循。所以TCP連接還要在TIME_WAIT狀態(tài)等待2倍MSL灭袁,這樣可以保證本次連接的所有數(shù)據(jù)都從網(wǎng)絡(luò)中消失逢唤。
4.5 什么是2MSL ?
MSL是Maximum Segment Lifetime英文的縮寫著恩,中文可以譯為“報(bào)文最大生存時(shí)間”伍茄,他是任何報(bào)文在網(wǎng)絡(luò)上存在的最長時(shí)間曹仗,超過這個(gè)時(shí)間報(bào)文將被丟棄啼器。因?yàn)閠cp報(bào)文(segment)是ip數(shù)據(jù)報(bào)(datagram)的數(shù)據(jù)部分损谦,具體稱謂請(qǐng)參見《數(shù)據(jù)在網(wǎng)絡(luò)各層中的稱呼》一文,而ip頭中有一個(gè)TTL域,TTL是time to live的縮寫,中文可以譯為“生存時(shí)間”涩蜘,這個(gè)生存時(shí)間是由源主機(jī)設(shè)置初始值但不是存的具體時(shí)間误窖,而是存儲(chǔ)了一個(gè)ip數(shù)據(jù)報(bào)可以經(jīng)過的最大路由數(shù),每經(jīng)過一個(gè)處理他的路由器此值就減1培漏,當(dāng)此值為0則數(shù)據(jù)報(bào)將被丟棄,同時(shí)發(fā)送ICMP報(bào)文通知源主機(jī)。RFC 793中規(guī)定MSL為2分鐘胸梆,實(shí)際應(yīng)用中常用的是30秒秽荤,1分鐘和2分鐘等晨继。
2MSL即兩倍的MSL餐屎,TCP的TIME_WAIT狀態(tài)也稱為2MSL等待狀態(tài),當(dāng)TCP的一端發(fā)起主動(dòng)關(guān)閉,在發(fā)出最后一個(gè)ACK包后菇曲,即第3次握手完成后發(fā)送了第四次握手的ACK包后就進(jìn)入了TIME_WAIT狀態(tài)孵户,必須在此狀態(tài)上停留兩倍的MSL時(shí)間,等待2MSL時(shí)間主要目的是怕最后一個(gè)ACK包對(duì)方?jīng)]收到胁镐,那么對(duì)方在超時(shí)后將重發(fā)第三次握手的FIN包,主動(dòng)關(guān)閉端接到重發(fā)的FIN包后可以再發(fā)一個(gè)ACK應(yīng)答包。在TIME_WAIT狀態(tài)時(shí)兩端的端口不能使用伴箩,要等到2MSL時(shí)間結(jié)束才可繼續(xù)使用。當(dāng)連接處于2MSL等待階段時(shí)任何遲到的報(bào)文段都將被丟棄。不過在實(shí)際應(yīng)用中可以通過設(shè)置SO_REUSEADDR選項(xiàng)達(dá)到不必等待2MSL時(shí)間結(jié)束再使用此端口瘫怜。
TTL與MSL是有關(guān)系的但不是簡單的相等的關(guān)系,MSL要大于等于TTL鲜屏。