為什么要有TIME_WAIT呢慈俯?
1.可靠地實(shí)現(xiàn)TCP全雙工連接的終止栏尚。
A發(fā)送FIN到B起愈,B收到FIN后發(fā)送ACK到A,然后再發(fā)送FIN到A,A最后發(fā)送ACK到B抬虽,之后進(jìn)入到TIME_WAIT狀態(tài)官觅。如果A到B的ACK丟失了,B沒有接到會(huì)怎樣阐污?這個(gè)時(shí)候A處于TIME_WAIT狀態(tài)休涤,B沒有接到ACK將會(huì)重新發(fā)送FIN,然后A重新發(fā)送ACK笛辟。
2.使得老的重復(fù)分節(jié)在網(wǎng)絡(luò)中消逝功氨。
假設(shè)在IP1的端口1和IP2的端口2之間有一個(gè)TCP連接,我們關(guān)閉這個(gè)連接手幢,過一會(huì)兒重連這個(gè)連接捷凄。需要知道的是TCP不允許已關(guān)閉連接的重復(fù)分節(jié)再出現(xiàn),所以需要TIME_WAIT围来,使得這些重復(fù)分節(jié)徹底消逝跺涤。(TCP中是可靠的服務(wù),當(dāng)數(shù)據(jù)包丟失會(huì)重傳管钳,當(dāng)有數(shù)據(jù)包迷路的情況下钦铁,如果不等待2MSL時(shí),當(dāng)客戶端以同樣地方式重新和服務(wù)建立連接后才漆,上一次迷路的數(shù)據(jù)包這時(shí)可能會(huì)到達(dá)服務(wù)牛曹,這時(shí)會(huì)造成舊包被重新讀取)
close_wait
close_wait產(chǎn)生的原因是當(dāng)某一端發(fā)送FIN醇滥,本端接收到就進(jìn)入close_wait狀態(tài)黎比,直到本端發(fā)送FIN。
所以說time_wait是主動(dòng)關(guān)閉的一方會(huì)經(jīng)歷的狀態(tài)鸳玩,close_wait是被動(dòng)關(guān)閉一方會(huì)經(jīng)歷的狀態(tài)阅虫。
什么情況下會(huì)產(chǎn)生大量的close_wait呢?
當(dāng)服務(wù)器端fork許多子進(jìn)程不跟,在這些子進(jìn)程中接收/發(fā)送颓帝,父進(jìn)程一直監(jiān)聽新的連接,sockfd套接字計(jì)數(shù)就會(huì)很大窝革,如果客戶端發(fā)送FIN過來购城,服務(wù)器端子進(jìn)程調(diào)用close使sockfd引用計(jì)數(shù)減1(沒有發(fā)送FIN給客戶端),但是不會(huì)關(guān)閉這個(gè)套接字虐译,這個(gè)時(shí)候就進(jìn)入了close_wait狀態(tài)瘪板。
或者是
對(duì)方發(fā)送FIN,我方忙于讀或者寫漆诽,沒有關(guān)閉連接侮攀。
如何避免time_wait?
使用SO_REUSEADDR選項(xiàng)锣枝,
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const voidvoid )&opt, sizeof(opt));
SO_REUSEADDR允許啟動(dòng)一個(gè)監(jiān)聽服務(wù)器并捆綁其眾所周知的端口,即使以前建立的將該端口用作他們的本地端口的連接仍存在兰英。也就是說允許某一個(gè)端口復(fù)用撇叁。*
如何避免close_wait?
主要思想是判斷對(duì)方是否關(guān)閉了這個(gè)套接字。
方法1:使用SO_KEEPALIVE套接字選項(xiàng)箭昵。
1税朴、client端連接正常,返回一個(gè)ACK.server端收到ACK后重置計(jì)時(shí)器,在2小時(shí)后在發(fā)送探測(cè).如果2小時(shí)內(nèi)連接上有數(shù)據(jù)傳輸,那么在該時(shí)間的基礎(chǔ)上向后推延2小時(shí)發(fā)送探測(cè)包;
2、客戶端異常關(guān)閉,或網(wǎng)絡(luò)斷開家制。client無(wú)響應(yīng),server收不到ACK,在一定時(shí)間(75秒)后重發(fā)keepalive packet, 并且重發(fā)一定次數(shù)(9次);
3、客戶端曾經(jīng)崩潰,但已經(jīng)重啟.server收到的探測(cè)響應(yīng)是一個(gè)RST,server端終止連接泡一。
方法2:我們也可以自己寫一個(gè)發(fā)送心跳包的線程颤殴,定期發(fā)送心跳包,如果對(duì)方關(guān)閉了套接字鼻忠,則我們會(huì)收到RST涵但。
如果服務(wù)器出了異常,百分之八九十都是下面兩種情況:
1.服務(wù)器保持了大量TIME_WAIT狀態(tài)
2.服務(wù)器保持了大量CLOSE_WAIT狀態(tài)
查看當(dāng)前狀態(tài)的命令: netstat -nat