令人討厭的CLOSE_第1頁(yè)
令人討厭的CLOSE_第2頁(yè)
令人討厭的CLOSE_第3頁(yè)
令人討厭的CLOSE_第4頁(yè)
全文預(yù)覽已結(jié)束

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、令人討厭的CLOSE_WAIT狀態(tài)的生成原因重用本地地址和端口從容關(guān)閉還是強(qiáng)行關(guān)閉?總結(jié)摘要:本文闡述了為何socket連接鎖定在CLOSE_WAIT狀態(tài),以及通過(guò)什么措施力求避免這種情況。不久前,我的Socket Client程序遇到了一個(gè)非常尷尬的錯(cuò)誤。它本來(lái)應(yīng)該在一個(gè)socket長(zhǎng)連接上持續(xù)不斷地向服務(wù)器 發(fā)送數(shù)據(jù),如果socket連接斷開,那么程序會(huì)自動(dòng)不斷地重試建立連接。有一天發(fā)現(xiàn)程序在不斷嘗試建立連接,但是總是失敗。用netstat查看,這個(gè)程序竟然有上千個(gè)socket連接處于CLOSE_WAIT狀態(tài),以至于達(dá)到了上限,所以無(wú)法建立新的socket連接了。為什么會(huì)這樣呢?它們?yōu)槭裁?/p>

2、會(huì)都處在CLOSE_WAIT狀態(tài)呢?CLOSE_WAIT狀態(tài)的生成原因首先我們知道,如果我們的Client程序處于CLOSE_WAIT狀態(tài)的話,說(shuō)明套接字是被動(dòng)關(guān)閉的!因?yàn)槿绻荢erver端主動(dòng)斷掉當(dāng)前連接的話,那么雙方關(guān)閉這個(gè)TCP連接共需要四個(gè)packet:Server - FIN - ClientServer - ACK - Client這時(shí)候Server端處于FIN_WAIT_2狀態(tài);而我們的程序處于CLOSE_WAIT狀態(tài)。Server - FIN ACK - ClientServer回應(yīng)了 ACK,那么Client的套接字才會(huì)真正置為CLOSED狀態(tài)。我們的程序處于CLOSE_W

3、AIT狀態(tài),而不是LAST_ACK狀態(tài),說(shuō)明還沒有發(fā)FIN給Server,那么可能是在關(guān)閉連接 之前還有許多數(shù)據(jù)要發(fā)送或者其他事要做,導(dǎo)致沒有發(fā)這個(gè)FIN packeto原因知道了,那么為什么不發(fā)FIN包呢,難道會(huì)在關(guān)閉己方連接前有那么多事情要做嗎?elssann舉例說(shuō),當(dāng)對(duì)方調(diào)用closesocket的時(shí)候,我的程序正在調(diào)用recv中,這時(shí)候有可能對(duì)方發(fā)送的FIN包我沒有 收到,而是由TCP代回了一個(gè)ACK包,所以我這邊套接字進(jìn)入CLOSE_WAIT狀態(tài)。所以他建議在這里判斷recv函數(shù)的返回值是否已出錯(cuò),是的話就主動(dòng)closesocket,這樣防止沒有接收到FIN包。因?yàn)榍懊嫖覀円呀?jīng)設(shè)置了

4、 recv超時(shí)時(shí)間為30秒,那么如果真的是超時(shí)了,這里收到的錯(cuò)誤應(yīng)該是WSAETIMEDOUT, 這種情況下也可以主動(dòng)關(guān)閉連接的。還有一個(gè)問題,為什么有數(shù)千個(gè)連接都處于這個(gè)狀態(tài)呢?難道那段時(shí)間內(nèi),服務(wù)器端總是主動(dòng)拆除我們的連接嗎?不管怎么樣,我們必須防止類似情況再度發(fā)生!首先,我們要保證原來(lái)的端口可以被重用,這可以通過(guò)設(shè)置SO_REUSEADDR套接字選項(xiàng)做到:重用本地地址和端口以前我總是一個(gè)端口不行,就換一個(gè)新的使用,所以導(dǎo)致讓數(shù)千個(gè)端口進(jìn)入CLOSE_WAIT狀態(tài)。如果下次還發(fā)生這種尷 尬狀況,我希望加一個(gè)限定,只是當(dāng)前這個(gè)端口處于CLOSE_WAIT狀態(tài)!在調(diào)用sockConnected

5、 = socket(AF_INET, SOCK_STREAM, 0);之后,我們要設(shè)置該套接字的選項(xiàng)來(lái)重用:/允許重用本地地址和端口:/這樣的好處是,即使socket斷了,調(diào)用前面的socket函數(shù)也不會(huì)占用另一個(gè),而是始終就是一個(gè)端口/這樣防止socket始終連接不上,那么按照原來(lái)的做法,會(huì)不斷地?fù)Q端口。int nREUSEADDR = 1;setsockopt(sockConnected,SOL_SOCKET,SO_REUSEADDR,(const char*)&nREUSEADDR,sizeof(int);教科書上是這么說(shuō)的:這樣,假如服務(wù)器關(guān)閉或者退出,造成本地地址和端口都處于TIME

6、_WAIT狀態(tài),那么SO_REUSEADDR就顯得非常有用。也許我們無(wú)法避免被凍結(jié)在CLOSE_WAIT狀態(tài)永遠(yuǎn)不出現(xiàn),但起碼可以保證不會(huì)占用新的端口。其次,我們要設(shè)置SO_LINGER套接字選項(xiàng):從容關(guān)閉還是強(qiáng)行關(guān)閉?LINGER是拖延的意思。默認(rèn)情況下(Win2k),SO_DONTLINGER套接字選項(xiàng)的是 1; SO_LINGER選項(xiàng)是,linger為l_onoff: 0,l_linger: 0。如果在發(fā)送數(shù)據(jù)的過(guò)程中(send()沒有完成,還有數(shù)據(jù)沒發(fā)送)而調(diào)用了 closesocket(),以前我們一般采取的措施是從容 關(guān)閉:因?yàn)樵谕顺龇?wù)或者每次重新建立socket之前,我都會(huì)先調(diào)

7、用/先將雙向的通訊關(guān)閉shutdown(sockConnected, SD_BOTH);/安全起見,每次建立Socket連接前,先把這個(gè)舊連接關(guān)閉closesocket(sockConnected);我們這次要這么做:設(shè)置SO_LINGER為零(亦即linger結(jié)構(gòu)中的l_onoff域設(shè)為非零,但l_linger為0),便不用擔(dān)心。losesocket調(diào)用進(jìn) 入鎖定狀態(tài)(等待完成),不論是否有排隊(duì)數(shù)據(jù)未發(fā)送或未被確認(rèn)。這種關(guān)閉方式稱為強(qiáng)行關(guān)閉,因?yàn)樘捉幼值奶撾娐?立即被復(fù)位,尚未發(fā)出的所有數(shù)據(jù)都會(huì)丟失。在遠(yuǎn)端的recv()調(diào)用都會(huì)失敗,并返回WSAECONNRESET錯(cuò)誤。在connect成功

8、建立連接之后設(shè)置該選項(xiàng):linger m_sLinger;m_sLinger.l_onoff = 1; / (在closesocket()調(diào)用,但是還有數(shù)據(jù)沒發(fā)送完畢的時(shí)候容許逗留)m_sLinger.l_linger = 0; / (容許逗留的時(shí)間為0秒)setsockopt(sockConnected,SOL_SOCKET,SO_LINGER,(const char*)&m_sLinger,sizeof(linger);另外:通常來(lái)說(shuō),一個(gè) CLOSE_WAIT會(huì)維持至少2個(gè)小時(shí)的時(shí)間。如果有個(gè)流氓特地寫了個(gè)程序,給你造成一堆的 CLOSE_WAI消耗你的資源,那么通常是等不到釋放那一刻,系統(tǒng)就已經(jīng)解決崩潰了。只能通過(guò)修改一下 TCP/IP的參數(shù),來(lái)縮短這個(gè)時(shí)間:修改tcp_keepalive_*系列參數(shù)有助于解決這個(gè)問題。tcp_keepalive_time : INTEGER默認(rèn)值是7200(2小時(shí))當(dāng)keepalive打開的情況下,TCP發(fā)送keepalive消息的頻率。(由于目前網(wǎng)絡(luò)攻擊等因素,造成 了利用這個(gè)進(jìn)行的攻擊很頻繁,曾經(jīng)也有cu的朋友提到過(guò),說(shuō)如果2邊建立了連接,然后不發(fā)送任何數(shù)據(jù)或者rst/fin消息, 那么持續(xù)的時(shí)間是不是就是2小時(shí),空連接攻擊?

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論