一、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)端口仍處于開放狀態(tài),準(zhǔn)備接收后續(xù)數(shù)據(jù)。 1),、LISTEN:首先服務(wù)端需要打開一個(gè)socket進(jìn)行監(jiān)聽,,狀態(tài)為L(zhǎng)ISTEN. /* The socket is listening for incoming connections. 偵聽來(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è)打開的連接,,雙方可以進(jìn)行或已經(jīng)在數(shù)據(jù)交互了,。/* The socket has an established connection. 代表一個(gè)打開的連接,數(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: 比較少見./* 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. 沒有任何連接狀態(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)用程序通過調(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)閉握手消息本身并沒有傳遞給接收端應(yīng)用程序,而是通過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)鬏敗D6.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上的任何讀寫操作(會(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)離開Time-Wait狀態(tài)并被刪除),,并為同樣一對(duì)地址上的新連接清理道路后,就不會(huì)再有舊實(shí)例發(fā)送的消息還存留在網(wǎng)絡(luò)中,。實(shí)際上,,平靜時(shí)間的長(zhǎng)度要依賴于具體實(shí)現(xiàn),因?yàn)闆]有機(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è)沒什么好說(shuō)的了,表示初始狀態(tài),。 LISTEN: 這個(gè)也是非常容易理解的一個(gè)狀態(tài),,表示服務(wù)器端的某個(gè)SOCKET處于監(jiān)聽狀態(tài),可以接受連接了,。 SYN_RCVD: 這個(gè)狀態(tài)表示接受到了SYN報(bào)文,,在正常情況下,這個(gè)狀態(tài)是服務(wù)器端的SOCKET在建立TCP連接時(shí)的三次握手會(huì)話過程中的一個(gè)中間狀態(tài),,很短暫,,基本上用netstat你是很難看到這種狀態(tài)的,除非你特意寫了一個(gè)客戶端測(cè)試程序,,故意將三次TCP握手過程中最后一個(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)一般是比較難見到的,而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)過FIN_WAIT_2狀態(tài),。 CLOSING: 這種狀態(tài)比較特殊,實(shí)際情況中應(yīng)該是很少見,,屬于一種比較罕見的例外狀態(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)文后,并沒有收到對(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ú)疑問地會(huì)回應(yīng)一個(gè)ACK報(bào)文給對(duì)方,此時(shí)則進(jìn)入到CLOSE_WAIT狀態(tài),。接下來(lái)呢,,實(shí)際上你真正需要考慮的事情是察看你是否還有數(shù)據(jù)發(fā)送給對(duì)方,如果沒有的話,,那么你也就可以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è)問題的回答,我自己分析后的結(jié)論(不一定保證100%正確): 1,、 為什么建立連接協(xié)議是三次握手,,而關(guān)閉連接卻是四次握手呢? 2,、 為什么TIME_WAIT狀態(tài)還需要等2MSL后才能返回到CLOSED狀態(tài),? |
|
來(lái)自: 娛天樂 > 《網(wǎng)絡(luò)編程》