參考文章:https://www.2cto.com/net/201209/157585.html
tcp狀態(tài):
LISTEN:偵聽(tīng)來(lái)自遠(yuǎn)方的TCP端口的連接請(qǐng)求
SYN-SENT:再發(fā)送連接請(qǐng)求后等待匹配的連接請(qǐng)求
SYN-RECEIVED:再收到和發(fā)送一個(gè)連接請(qǐng)求后等待對(duì)方對(duì)連接請(qǐng)求的確認(rèn)
ESTABLISHED:代表一個(gè)打開(kāi)的連接
FIN-WAIT-1:等待遠(yuǎn)程TCP連接中斷請(qǐng)求驻债,或先前的連接中斷請(qǐng)求的確認(rèn)
FIN-WAIT-2:從遠(yuǎn)程TCP等待連接中斷請(qǐng)求
CLOSE-WAIT:等待從本地用戶發(fā)來(lái)的連接中斷請(qǐng)求
CLOSING:等待遠(yuǎn)程TCP對(duì)連接中斷的確認(rèn)
LAST-ACK:等待原來(lái)的發(fā)向遠(yuǎn)程TCP的連接中斷請(qǐng)求的確認(rèn)TIME-WAIT:等待足夠的時(shí)間以確保遠(yuǎn)程TCP接收到連接中斷請(qǐng)求的確認(rèn)
CLOSED:沒(méi)有任何連接狀態(tài)
image
image
image
image
image
- TCP是一個(gè)面向連接的協(xié)議乳规,所以在連接雙方發(fā)送數(shù)據(jù)之前,都需要首先建立一條連接合呐。這和前面講到的協(xié)議完全不同暮的。前面講的所有協(xié)議都只是發(fā)送數(shù)據(jù)而已,大多數(shù)都不關(guān)心發(fā)送的數(shù)據(jù)是不是送到淌实,UDP尤其明顯冻辩,從編程的角度來(lái)說(shuō),UDP編程也要簡(jiǎn)單的多----UDP都不用考慮數(shù)據(jù)分片拆祈。書中用telnet登陸退出來(lái)解釋TCP協(xié)議連接的建立和中止的過(guò)程恨闪,可以看到,TCP連接的建立可以簡(jiǎn)單的稱為三次握手放坏,而連接的中止則可以叫做四次握手咙咽。
- 1.連接的建立在建立連接的時(shí)候,客戶端首先向服務(wù)器申請(qǐng)打開(kāi)某一個(gè)端口(用SYN段等于1的TCP報(bào)文)淤年,然后服務(wù)器端發(fā)回一個(gè)ACK報(bào)文通知客戶端請(qǐng)求報(bào)文收到犁珠,客戶端收到確認(rèn)報(bào)文以后再次發(fā)出確認(rèn)報(bào)文確認(rèn)剛才服務(wù)器端發(fā)出的確認(rèn)報(bào)文(繞口么),至此互亮,連接的建立完成犁享。這就叫做三次握手。如果打算讓雙方都做好準(zhǔn)備的話豹休,一定要發(fā)送三次報(bào)文炊昆,而且只需要三次報(bào)文就可以了⊥可以想見(jiàn)凤巨,如果再加上TCP的超時(shí)重傳機(jī)制,那么TCP就完全可以保證一個(gè)數(shù)據(jù)包被送到目的地洛搀。
- 2.結(jié)束連接TCP有一個(gè)特別的概念叫做half-close敢茁,這個(gè)概念是說(shuō),TCP的連接是全雙工(可以同時(shí)發(fā)送和接收)連接留美,因此在關(guān)閉連接的時(shí)候彰檬,必須關(guān)閉傳和送兩個(gè)方向上的連接伸刃。客戶機(jī)給服務(wù)器一個(gè)FIN為1的TCP報(bào)文逢倍,然后服務(wù)器返回給客戶端一個(gè)確認(rèn)ACK報(bào)文捧颅,并且發(fā)送一個(gè)FIN報(bào)文,當(dāng)客戶機(jī)回復(fù)ACK報(bào)文后(四次握手)较雕,連接就結(jié)束了碉哑。
- 3.最大報(bào)文長(zhǎng)度在建立連接的時(shí)候,通信的雙方要互相確認(rèn)對(duì)方的最大報(bào)文長(zhǎng)度(MSS)亮蒋,以便通信扣典。一般這個(gè)SYN長(zhǎng)度是MTU減去固定IP首部和TCP首部長(zhǎng)度。對(duì)于一個(gè)以太網(wǎng)慎玖,一般可以達(dá)到1460字節(jié)激捏。當(dāng)然如果對(duì)于非本地的IP,這個(gè)MSS可能就只有536字節(jié)凄吏,而且远舅,如果中間的傳輸網(wǎng)絡(luò)的MSS更佳的小的話,這個(gè)值還會(huì)變得更小痕钢。
- 4.TCP的狀態(tài)遷移圖書P182頁(yè)給出了TCP的狀態(tài)圖图柏,這是一個(gè)看起來(lái)比較復(fù)雜的狀態(tài)遷移圖,因?yàn)樗藘蓚€(gè)部分---服務(wù)器的狀態(tài)遷移和客戶端的狀態(tài)遷移任连,如果從某一個(gè)角度出發(fā)來(lái)看這個(gè)圖蚤吹,就會(huì)清晰許多,這里面的服務(wù)器和客戶端都不是絕對(duì)的随抠,發(fā)送數(shù)據(jù)的就是客戶端裁着,接受數(shù)據(jù)的就是服務(wù)器。
- 4.1.客戶端應(yīng)用程序的狀態(tài)遷移圖客戶端的狀態(tài)可以用如下的流程來(lái)表示:CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED以上流程是在程序正常的情況下應(yīng)該有的流程拱她,從書中的圖中可以看到二驰,在建立連接時(shí),當(dāng)客戶端收到SYN報(bào)文的ACK以后秉沼,客戶端就打開(kāi)了數(shù)據(jù)交互地連接桶雀。而結(jié)束連接則通常是客戶端主動(dòng)結(jié)束的,客戶端結(jié)束應(yīng)用程序以后唬复,需要經(jīng)歷FIN_WAIT_1矗积,F(xiàn)IN_WAIT_2等狀態(tài),這些狀態(tài)的遷移就是前面提到的結(jié)束連接的四次握手敞咧。
- 4.2.服務(wù)器的狀態(tài)遷移圖服務(wù)器的狀態(tài)可以用如下的流程來(lái)表示:CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED在建立連接的時(shí)候棘捣,服務(wù)器端是在第三次握手之后才進(jìn)入數(shù)據(jù)交互狀態(tài),而關(guān)閉連接則是在關(guān)閉連接的第二次握手以后(注意不是第四次)休建。而關(guān)閉以后還要等待客戶端給出最后的ACK包才能進(jìn)入初始的狀態(tài)乍恐。
- 4.3.其他狀態(tài)遷移書中的圖還有一些其他的狀態(tài)遷移评疗,這些狀態(tài)遷移針對(duì)服務(wù)器和客戶端兩方面的總結(jié)如下LISTEN->SYN_SENT,對(duì)于這個(gè)解釋就很簡(jiǎn)單了禁熏,服務(wù)器有時(shí)候也要打開(kāi)連接的嘛壤巷。SYN_SENT->SYN收到邑彪,服務(wù)器和客戶端在SYN_SENT狀態(tài)下如果收到SYN數(shù)據(jù)報(bào)瞧毙,則都需要發(fā)送SYN的ACK數(shù)據(jù)報(bào)并把自己的狀態(tài)調(diào)整到SYN收到狀態(tài),準(zhǔn)備進(jìn)入ESTABLISHEDSYN_SENT->CLOSED寄症,在發(fā)送超時(shí)的情況下宙彪,會(huì)返回到CLOSED狀態(tài)。SYN_收到->LISTEN有巧,如果受到RST包释漆,會(huì)返回到LISTEN狀態(tài)。SYN_收到->FIN_WAIT_1篮迎,這個(gè)遷移是說(shuō)男图,可以不用到ESTABLISHED狀態(tài),而可以直接跳轉(zhuǎn)到FIN_WAIT_1狀態(tài)并等待關(guān)閉甜橱。
- 4.4.2MSL等待狀態(tài)書中給的圖里面逊笆,有一個(gè)TIME_WAIT等待狀態(tài),這個(gè)狀態(tài)又叫做2MSL狀態(tài)岂傲,說(shuō)的是在TIME_WAIT2發(fā)送了最后一個(gè)ACK數(shù)據(jù)報(bào)以后难裆,要進(jìn)入TIME_WAIT狀態(tài),這個(gè)狀態(tài)是防止最后一次握手的數(shù)據(jù)報(bào)沒(méi)有傳送到對(duì)方那里而準(zhǔn)備的(注意這不是四次握手镊掖,這是第四次握手的保險(xiǎn)狀態(tài))乃戈。這個(gè)狀態(tài)在很大程度上保證了雙方都可以正常結(jié)束,但是亩进,問(wèn)題也來(lái)了症虑。由于插口的2MSL狀態(tài)(插口是IP和端口對(duì)的意思,socket)归薛,使得應(yīng)用程序在2MSL時(shí)間內(nèi)是無(wú)法再次使用同一個(gè)插口的侦讨,對(duì)于客戶程序還好一些,但是對(duì)于服務(wù)程序苟翻,例如httpd韵卤,它總是要使用同一個(gè)端口來(lái)進(jìn)行服務(wù),而在2MSL時(shí)間內(nèi)崇猫,啟動(dòng)httpd就會(huì)出現(xiàn)錯(cuò)誤(插口被使用)沈条。為了避免這個(gè)錯(cuò)誤,服務(wù)器給出了一個(gè)平靜時(shí)間的概念诅炉,這是說(shuō)在2MSL時(shí)間內(nèi)蜡歹,雖然可以重新啟動(dòng)服務(wù)器屋厘,但是這個(gè)服務(wù)器還是要平靜的等待2MSL時(shí)間的過(guò)去才能進(jìn)行下一次連接。
- 4.5.FIN_WAIT_2狀態(tài)這就是著名的半關(guān)閉的狀態(tài)了月而,這是在關(guān)閉連接時(shí)汗洒,客戶端和服務(wù)器兩次握手之后的狀態(tài)。在這個(gè)狀態(tài)下父款,應(yīng)用程序還有接受數(shù)據(jù)的能力溢谤,但是已經(jīng)無(wú)法發(fā)送數(shù)據(jù),但是也有一種可能是憨攒,客戶端一直處于FIN_WAIT_2狀態(tài)世杀,而服務(wù)器則一直處于WAIT_CLOSE狀態(tài),而直到應(yīng)用層來(lái)決定關(guān)閉這個(gè)狀態(tài)肝集。
- 5.RST瞻坝,同時(shí)打開(kāi)和同時(shí)關(guān)閉RST是另一種關(guān)閉連接的方式,應(yīng)用程序應(yīng)該可以判斷RST包的真實(shí)性杏瞻,即是否為異常中止所刀。而同時(shí)打開(kāi)和同時(shí)關(guān)閉則是兩種特殊的TCP狀態(tài),發(fā)生的概率很小捞挥。
- 6.TCP服務(wù)器設(shè)計(jì)前面曾經(jīng)講述過(guò)UDP的服務(wù)器設(shè)計(jì)浮创,可以發(fā)現(xiàn)UDP的服務(wù)器完全不需要所謂的并發(fā)機(jī)制,它只要建立一個(gè)數(shù)據(jù)輸入隊(duì)列就可以树肃。但是TCP不同蒸矛,TCP服務(wù)器對(duì)于每一個(gè)連接都需要建立一個(gè)獨(dú)立的進(jìn)程(或者是輕量級(jí)的,線程)胸嘴,來(lái)保證對(duì)話的獨(dú)立性雏掠。所以TCP服務(wù)器是并發(fā)的。而且TCP還需要配備一個(gè)呼入連接請(qǐng)求隊(duì)列(UDP服務(wù)器也同樣不需要)劣像,來(lái)為每一個(gè)連接請(qǐng)求建立對(duì)話進(jìn)程乡话,這也就是為什么各種TCP服務(wù)器都有一個(gè)最大連接數(shù)的原因。而根據(jù)源主機(jī)的IP和端口號(hào)碼耳奕,服務(wù)器可以很輕松的區(qū)別出不同的會(huì)話绑青,來(lái)進(jìn)行數(shù)據(jù)的分發(fā)。