一、Linux服務(wù)器上11種網(wǎng)絡(luò)連接狀態(tài): 通常情況下,一個(gè)正常的TCP連接,都會(huì)有三個(gè)階段:1、TCP三次握手; 2、數(shù)據(jù)傳送; 3、TCP四次揮手 注:以下說(shuō)明最好能結(jié)合”圖:TCP的狀態(tài)機(jī)”來(lái)理解。 SYN: (同步序列編號(hào),Synchronize Sequence Numbers)該標(biāo)志僅在三次握手建立TCP連接時(shí)有效。表示一個(gè)新的TCP連接請(qǐng)求。 ACK: (確認(rèn)編號(hào),Acknowledgement Number)是對(duì)TCP請(qǐng)求的確認(rèn)標(biāo)志,同時(shí)提示對(duì)端系統(tǒng)已經(jīng)成功接收所有數(shù)據(jù)。 FIN: (結(jié)束標(biāo)志,FINish)用來(lái)結(jié)束一個(gè)TCP回話.但對(duì)應(yīng)端口仍處于開(kāi)放狀態(tài),準(zhǔn)備接收后續(xù)數(shù)據(jù)。 1)、LISTEN:首先服務(wù)端需要打開(kāi)一個(gè)socket進(jìn)行監(jiān)聽(tīng),狀態(tài)為L(zhǎng)ISTEN. /* The socket is listening for incoming connections. 偵聽(tīng)來(lái)自遠(yuǎn)方TCP端口的連接請(qǐng)求 */ 3)、SYN_RECV:服務(wù)端應(yīng)發(fā)出ACK確認(rèn)客戶端的SYN,同時(shí)自己向客戶端發(fā)送一個(gè)SYN. 之后狀態(tài)置為SYN_RECV /* A connection request has been received from the network. 在收到和發(fā)送一個(gè)連接請(qǐng)求后等待對(duì)連接請(qǐng)求的確認(rèn) */ 4)、ESTABLISHED: 代表一個(gè)打開(kāi)的連接,雙方可以進(jìn)行或已經(jīng)在數(shù)據(jù)交互了。/* The socket has an established connection. 代表一個(gè)打開(kāi)的連接,數(shù)據(jù)可以傳送給用戶 */ 5)、FIN_WAIT1:主動(dòng)關(guān)閉(active close)端應(yīng)用程序調(diào)用close,于是其TCP發(fā)出FIN請(qǐng)求主動(dòng)關(guān)閉連接,之后進(jìn)入FIN_WAIT1狀態(tài)./* The socket is closed, and the connection is shutting down. 等待遠(yuǎn)程TCP的連接中斷請(qǐng)求,或先前的連接中斷請(qǐng)求的確認(rèn) */ 6)、CLOSE_WAIT:被動(dòng)關(guān)閉(passive close)端TCP接到FIN后,就發(fā)出ACK以回應(yīng)FIN請(qǐng)求(它的接收也作為文件結(jié)束符傳遞給上層應(yīng)用程序),并進(jìn)入CLOSE_WAIT. /* The remote end has shut down, waiting for the socket to close. 等待從本地用戶發(fā)來(lái)的連接中斷請(qǐng)求 */ 7)、FIN_WAIT2:主動(dòng)關(guān)閉端接到ACK后,就進(jìn)入了FIN-WAIT-2 ./* Connection is closed, and the socket is waiting for a shutdown from the remote end. 從遠(yuǎn)程TCP等待連接中斷請(qǐng)求 */ 8)、LAST_ACK:被動(dòng)關(guān)閉端一段時(shí)間后,接收到文件結(jié)束符的應(yīng)用程序?qū)⒄{(diào)用CLOSE關(guān)閉連接。這導(dǎo)致它的TCP也發(fā)送一個(gè) FIN,等待對(duì)方的ACK.就進(jìn)入了LAST-ACK . /* The remote end has shut down, and the socket is closed. Waiting for acknowledgement. 等待原來(lái)發(fā)向遠(yuǎn)程TCP的連接中斷請(qǐng)求的確認(rèn) */ 9)、TIME_WAIT:在主動(dòng)關(guān)閉端接收到FIN后,TCP就發(fā)送ACK包,并進(jìn)入TIME-WAIT狀態(tài)。/* The socket is waiting after close to handle packets still in the network.等待足夠的時(shí)間以確保遠(yuǎn)程TCP接收到連接中斷請(qǐng)求的確認(rèn) */ 10)、CLOSING: 比較少見(jiàn)./* Both sockets are shut down but we still don’t have all our data sent. 等待遠(yuǎn)程TCP對(duì)連接中斷的確認(rèn) */ 11)、CLOSED: 被動(dòng)關(guān)閉端在接受到ACK包后,就進(jìn)入了closed的狀態(tài)。連接結(jié)束./* The socket is not being used. 沒(méi)有任何連接狀態(tài) */ 二、關(guān)于長(zhǎng)連接和短連接: 一個(gè)應(yīng)用至于到底是該使用短連接還是長(zhǎng)連接,應(yīng)該視具體情況而定。一般的應(yīng)用應(yīng)該使用長(zhǎng)連接。 tcp 四次揮手 TCP協(xié)議有一個(gè)優(yōu)雅的關(guān)閉(graceful close)機(jī)制,以保證應(yīng)用程序在關(guān)閉連接時(shí)不必?fù)?dān)心正在傳輸?shù)臄?shù)據(jù)會(huì)丟失。如第4.5節(jié)的壓縮示例程序所示,這個(gè)機(jī)制還設(shè)計(jì)為允許兩個(gè)方向的數(shù)據(jù)傳輸相互獨(dú)立地終止。關(guān)閉機(jī)制的工作流程是:應(yīng)用程序通過(guò)調(diào)用連接套接字的close()方法或shutdownOutput()方法表明數(shù)據(jù)已經(jīng)發(fā)送完畢。此刻,底層的TCP實(shí)現(xiàn)首先將留存在SendQ隊(duì)列中的數(shù)據(jù)傳輸出去(還要依賴于另一端RecvQ隊(duì)列的剩余空間),然后向另一端發(fā)送一個(gè)關(guān)閉TCP連接的握手消息。該關(guān)閉握手消息可以看作是流終止標(biāo)志:它告訴接收端TCP不會(huì)再有新的數(shù)據(jù)傳入RecvQ隊(duì)列了。(注意,關(guān)閉握手消息本身并沒(méi)有傳遞給接收端應(yīng)用程序,而是通過(guò)read()方法返回-1來(lái)指示其在字節(jié)流中的位置。)正在關(guān)閉的TCP將等待其關(guān)閉握手消息的確認(rèn)信息,該確認(rèn)信息表明在連接上傳輸?shù)乃袛?shù)據(jù)已經(jīng)安全地傳輸?shù)搅薘ecvQ中。只要收到了確認(rèn)消息,該連接就變成"半關(guān)閉(Half closed)"狀態(tài)。直到連接的另一個(gè)方向上收到了對(duì)稱的握手消息后,連接才完全關(guān)閉--也就是說(shuō),連接的兩端都表明它們?cè)贈(zèng)]有數(shù)據(jù)要發(fā)送了。 TCP連接的關(guān)閉事件序列可能以兩種方式發(fā)生:一種方式是先由一個(gè)應(yīng)用程序調(diào)用close()方法(或shutdownOutput()方法),并在另一端調(diào)用close()方法之前完成其關(guān)閉握手消息;另一種方式是兩端同時(shí)調(diào)用close()方法,它們的關(guān)閉握手消息在網(wǎng)絡(luò)上交叉?zhèn)鬏?。圖6.10展示了以第一種方式關(guān)閉連接時(shí),底層實(shí)現(xiàn)中的事件序列。關(guān)閉握手消息已經(jīng)發(fā)送,套接字?jǐn)?shù)據(jù)結(jié)構(gòu)的狀態(tài)也已經(jīng)設(shè)置為"Closing"(專業(yè)術(shù)語(yǔ)稱為"FIN_WAIT_1"),然后close()調(diào)用返回。完成這些工作后,將禁止在該Socket上的任何讀寫(xiě)操作(會(huì)拋出異常)。當(dāng)收到關(guān)閉握手確認(rèn)消息后,套接字?jǐn)?shù)據(jù)結(jié)構(gòu)的狀態(tài)則改變?yōu)?半關(guān)閉"(專業(yè)術(shù)語(yǔ)稱為"FIN_WAIT_2"),這種狀態(tài)將一直持續(xù),直到接收到另一端的關(guān)閉握手消息 關(guān)閉TCP連接的最后微妙之處在于對(duì)Time-Wait狀態(tài)的需要。TCP規(guī)范要求在終止連接時(shí),兩端的關(guān)閉握手都完成后,至少要有一個(gè)套接字在Time-Wait狀態(tài)保持一段時(shí)間。這個(gè)要求的提出是由于消息在網(wǎng)絡(luò)中傳輸時(shí)可能延遲。如果在連接兩端都完成了關(guān)閉握手后,它們都移除了其底層數(shù)據(jù)結(jié)構(gòu),而此時(shí)在同樣一對(duì)套接字地址之間又立即建立了新的連接,那么前一個(gè)連接在網(wǎng)絡(luò)上傳輸時(shí)延遲的消息就可能在新連接建立后到達(dá)。由于其包含了相同的源地址和目的地址,舊消息就會(huì)被錯(cuò)誤地認(rèn)為是屬于新連接的,其包含的數(shù)據(jù)就可能被錯(cuò)誤地分配到應(yīng)用程序中。 雖然這種情形可能很少發(fā)生,TCP還是使用了包括Time-Wait狀態(tài)在內(nèi)的多種機(jī)制對(duì)其進(jìn)行防范。Time-Wait狀態(tài)用于保證每個(gè)TCP連接都在一段平靜時(shí)間內(nèi)結(jié)束,這期間不會(huì)有數(shù)據(jù)發(fā)送。平靜時(shí)間的長(zhǎng)度應(yīng)該等于分組報(bào)文在網(wǎng)絡(luò)上存留的最長(zhǎng)時(shí)間的兩倍。因此,當(dāng)一個(gè)連接完全結(jié)束(即套接字?jǐn)?shù)據(jù)結(jié)構(gòu)離開(kāi)Time-Wait狀態(tài)并被刪除),并為同樣一對(duì)地址上的新連接清理道路后,就不會(huì)再有舊實(shí)例發(fā)送的消息還存留在網(wǎng)絡(luò)中。實(shí)際上,平靜時(shí)間的長(zhǎng)度要依賴于具體實(shí)現(xiàn),因?yàn)闆](méi)有機(jī)制能真正限制分組報(bào)文在網(wǎng)絡(luò)上能夠延遲的時(shí)間。通常使用的時(shí)間范圍是4分鐘減到30秒,或更短。 Time-Wait狀態(tài)最重要的作用是,只要底層套接字?jǐn)?shù)據(jù)結(jié)構(gòu)還存在,就不允許在相同的本地端口上關(guān)聯(lián)其他套接字。尤其是試圖使用該端口創(chuàng)建新的Socket實(shí)例時(shí),將拋出IOException異常。 1 2 CLOSED: 這個(gè)沒(méi)什么好說(shuō)的了,表示初始狀態(tài)。 LISTEN: 這個(gè)也是非常容易理解的一個(gè)狀態(tài),表示服務(wù)器端的某個(gè)SOCKET處于監(jiān)聽(tīng)狀態(tài),可以接受連接了。 SYN_RCVD: 這個(gè)狀態(tài)表示接受到了SYN報(bào)文,在正常情況下,這個(gè)狀態(tài)是服務(wù)器端的SOCKET在建立TCP連接時(shí)的三次握手會(huì)話過(guò)程中的一個(gè)中間狀態(tài),很短暫,基本上用netstat你是很難看到這種狀態(tài)的,除非你特意寫(xiě)了一個(gè)客戶端測(cè)試程序,故意將三次TCP握手過(guò)程中最后一個(gè)ACK報(bào)文不予發(fā)送。因此這種狀態(tài)時(shí),當(dāng)收到客戶端的ACK報(bào)文后,它會(huì)進(jìn)入到ESTABLISHED狀態(tài)。 SYN_SENT: 這個(gè)狀態(tài)與SYN_RCVD遙想呼應(yīng),當(dāng)客戶端SOCKET執(zhí)行CONNECT連接時(shí),它首先發(fā)送SYN報(bào)文,因此也隨即它會(huì)進(jìn)入到了SYN_SENT狀態(tài),并等待服務(wù)端的發(fā)送三次握手中的第2個(gè)報(bào)文。SYN_SENT狀態(tài)表示客戶端已發(fā)送SYN報(bào)文。 ESTABLISHED:這個(gè)容易理解了,表示連接已經(jīng)建立了。 FIN_WAIT_1: 這個(gè)狀態(tài)要好好解釋一下,其實(shí)FIN_WAIT_1和FIN_WAIT_2狀態(tài)的真正含義都是表示等待對(duì)方的FIN報(bào)文。而這兩種狀態(tài)的區(qū)別是:FIN_WAIT_1狀態(tài)實(shí)際上是當(dāng)SOCKET在ESTABLISHED狀態(tài)時(shí),它想主動(dòng)關(guān)閉連接,向?qū)Ψ桨l(fā)送了FIN報(bào)文,此時(shí)該SOCKET即進(jìn)入到FIN_WAIT_1狀態(tài)。而當(dāng)對(duì)方回應(yīng)ACK報(bào)文后,則進(jìn)入到FIN_WAIT_2狀態(tài),當(dāng)然在實(shí)際的正常情況下,無(wú)論對(duì)方何種情況下,都應(yīng)該馬上回應(yīng)ACK報(bào)文,所以FIN_WAIT_1狀態(tài)一般是比較難見(jiàn)到的,而FIN_WAIT_2狀態(tài)還有時(shí)常??梢杂胣etstat看到。 FIN_WAIT_2:上面已經(jīng)詳細(xì)解釋了這種狀態(tài),實(shí)際上FIN_WAIT_2狀態(tài)下的SOCKET,表示半連接,也即有一方要求close連接,但另外還告訴對(duì)方,我暫時(shí)還有點(diǎn)數(shù)據(jù)需要傳送給你,稍后再關(guān)閉連接。 TIME_WAIT: 表示收到了對(duì)方的FIN報(bào)文,并發(fā)送出了ACK報(bào)文,就等2MSL后即可回到CLOSED可用狀態(tài)了。如果FIN_WAIT_1狀態(tài)下,收到了對(duì)方同時(shí)帶FIN標(biāo)志和ACK標(biāo)志的報(bào)文時(shí),可以直接進(jìn)入到TIME_WAIT狀態(tài),而無(wú)須經(jīng)過(guò)FIN_WAIT_2狀態(tài)。 CLOSING: 這種狀態(tài)比較特殊,實(shí)際情況中應(yīng)該是很少見(jiàn),屬于一種比較罕見(jiàn)的例外狀態(tài)。正常情況下,當(dāng)你發(fā)送FIN報(bào)文后,按理來(lái)說(shuō)是應(yīng)該先收到(或同時(shí)收到)對(duì)方的ACK報(bào)文,再收到對(duì)方的FIN報(bào)文。但是CLOSING狀態(tài)表示你發(fā)送FIN報(bào)文后,并沒(méi)有收到對(duì)方的ACK報(bào)文,反而卻也收到了對(duì)方的FIN報(bào)文。什么情況下會(huì)出現(xiàn)此種情況呢?其實(shí)細(xì)想一下,也不難得出結(jié)論:那就是如果雙方幾乎在同時(shí)close一個(gè)SOCKET的話,那么就出現(xiàn)了雙方同時(shí)發(fā)送FIN報(bào)文的情況,也即會(huì)出現(xiàn)CLOSING狀態(tài),表示雙方都正在關(guān)閉SOCKET連接。 CLOSE_WAIT: 這種狀態(tài)的含義其實(shí)是表示在等待關(guān)閉。怎么理解呢?當(dāng)對(duì)方close一個(gè)SOCKET后發(fā)送FIN報(bào)文給自己,你系統(tǒng)毫無(wú)疑問(wèn)地會(huì)回應(yīng)一個(gè)ACK報(bào)文給對(duì)方,此時(shí)則進(jìn)入到CLOSE_WAIT狀態(tài)。接下來(lái)呢,實(shí)際上你真正需要考慮的事情是察看你是否還有數(shù)據(jù)發(fā)送給對(duì)方,如果沒(méi)有的話,那么你也就可以close這個(gè)SOCKET,發(fā)送FIN報(bào)文給對(duì)方,也即關(guān)閉連接。所以你在CLOSE_WAIT狀態(tài)下,需要完成的事情是等待你去關(guān)閉連接。 LAST_ACK: 這個(gè)狀態(tài)還是比較容易好理解的,它是被動(dòng)關(guān)閉一方在發(fā)送FIN報(bào)文后,最后等待對(duì)方的ACK報(bào)文。當(dāng)收到ACK報(bào)文后,也即可以進(jìn)入到CLOSED可用狀態(tài)了。 最后有2個(gè)問(wèn)題的回答,我自己分析后的結(jié)論(不一定保證100%正確): 1、 為什么建立連接協(xié)議是三次握手,而關(guān)閉連接卻是四次握手呢? 2、 為什么TIME_WAIT狀態(tài)還需要等2MSL后才能返回到CLOSED狀態(tài)? |
|
來(lái)自: 娛天樂(lè) > 《網(wǎng)絡(luò)編程》