特黄特色三级在线观看免费,看黄色片子免费,色综合久,欧美在线视频看看,高潮胡言乱语对白刺激国产,伊人网成人,中文字幕亚洲一碰就硬老熟妇

學(xué)習(xí)啦>學(xué)習(xí)英語>英語其它>

close wait是什么

時(shí)間: 玉蓮928 分享

  close wait的意思到底是什么?下面是學(xué)習(xí)啦小編給大家整理的close wait是什么,供大家參閱!

  close wait是什么

  等待結(jié)束

  淺談CLOSE WAIT

  TCP 有很多連接狀態(tài),每一個都夠聊十塊錢兒的,比如我們以前討論過TIME_WAIT 和FIN_WAIT1,最近時(shí)不時(shí)聽人提起 CLOSE_WAIT,感覺有必要梳理一下。

  所謂 CLOSE_WAIT,借用某位大牛的話來說應(yīng)該倒過來叫做 WAIT_CLOSE,也就是說「等待關(guān)閉」,如果你還不理解其含義,可以看看 TCP 關(guān)閉連接時(shí)的圖例:

  TCP Close

  不要被圖中的 client 和 server 所迷惑,你只要記住:主動關(guān)閉的一方發(fā)出 FIN 包,被動關(guān)閉的一方響應(yīng) ACK 包,此時(shí),被動關(guān)閉的一方就進(jìn)入了 CLOSE_WAIT 狀態(tài)。如果一切正常,稍后被動關(guān)閉的一方也會發(fā)出 FIN 包,然后遷移到 LAST_ACK 狀態(tài)。

  通常,CLOSE_WAIT 狀態(tài)在服務(wù)器停留時(shí)間很短,如果你發(fā)現(xiàn)大量的 CLOSE_WAIT 狀態(tài),那么就意味著被動關(guān)閉的一方?jīng)]有及時(shí)發(fā)出 FIN 包,一般有如下幾種可能:

  程序問題:代碼層面遺漏或者死循環(huán)之類的,沒有 close 相應(yīng)的 socket 連接。

  響應(yīng)太慢:對方已經(jīng) timeout 了,本方還忙于耗時(shí)邏輯,導(dǎo)致 close 被延后。

  BACKLOG 太大:隊(duì)列堆積嚴(yán)重,導(dǎo)致多余的請求來不及消費(fèi)就被關(guān)閉了。

  如果遭遇了 CLOSE_WAIT 故障,那么需要立刻通過「netstat」或者「ss」命令來判斷 CLOSE_WAIT 連接是哪些進(jìn)程引起的,如果是我們自己寫的一些程序,比如用 HttpClient 自定義的蜘蛛,那么八九不離十是忘記了 close 相應(yīng)的 socket,如果是一些使用廣泛的程序,比如 Tomcat 之類的,那么不太可能是它們自身的 BUG,更可能是響應(yīng)速度太慢或者 BACKLOG 設(shè)置過大導(dǎo)致的故障。

  此外還有一點(diǎn)需要說明:按照前面圖例所示,當(dāng)被動關(guān)閉的一方處于 CLOSE_WAIT 狀態(tài)時(shí),主動關(guān)閉的一方處于 FIN_WAIT2 狀態(tài)。 那么為什么我們總聽說 CLOSE_WAIT 狀態(tài)過多的故障,但是卻相對少聽說 FIN_WAIT2 狀態(tài)過多的故障呢?這是因?yàn)?Linux 有一個「tcp_fin_timeout」設(shè)置,控制了 FIN_WAIT2 的最大生命周期。壞消息是 CLOSE_WAIT 沒有類似的設(shè)置,如果不重啟進(jìn)程,那么 CLOSE_WAIT 狀態(tài)很可能會永遠(yuǎn)持續(xù)下去;好消息是如果連接開啟了 keepalive機(jī)制,那么可以通過對應(yīng)的設(shè)置來清理無效連接,不過 keepalive 是治標(biāo)不治本的方法,還是應(yīng)該對照前面的解釋找到問題的癥結(jié)才對。

  本來想多寫點(diǎn)的,但是著急下班回家,就寫到這吧,結(jié)尾推薦兩個案例:

  PHP升級導(dǎo)致系統(tǒng)負(fù)載過高問題分析

  又見CLOSE_WAIT

  CLOSE WAIT狀態(tài)的生成原因

  首先我們知道,如果我們的Client程序處于CLOSE_WAIT狀態(tài)的話,說明套接字是被動關(guān)閉的!

  因?yàn)槿绻荢erver端主動斷掉當(dāng)前連接的話,那么雙方關(guān)閉這個TCP連接共需要四個packet:

  Server ---> FIN ---> Client

  Server <--- ACK <--- Client

  這時(shí)候Server端處于FIN_WAIT_2狀態(tài);而我們的程序處于CLOSE_WAIT狀態(tài)。

  Server <--- FIN <--- Client

  這時(shí)Client發(fā)送FIN給Server,Client就置為LAST_ACK狀態(tài)。

  Server ---> ACK ---> Client

  Server回應(yīng)了ACK,那么Client的套接字才會真正置為CLOSED狀態(tài)。

  我們的程序處于CLOSE_WAIT狀態(tài),而不是LAST_ACK狀態(tài),說明還沒有發(fā)FIN給Server,那么可能是在關(guān)閉連接之前還有許多數(shù)據(jù)要發(fā)送或者其他事要做,導(dǎo)致沒有發(fā)這個FIN packet。

  原因知道了,那么為什么不發(fā)FIN包呢,難道會在關(guān)閉己方連接前有那么多事情要做嗎?

  elssann舉例說,當(dāng)對方調(diào)用closesocket的時(shí)候,我的程序正在調(diào)用recv中,這時(shí)候有可能對方發(fā)送的FIN包我沒有收到,而是由TCP代回了一個ACK包,所以我這邊套接字進(jìn)入CLOSE_WAIT狀態(tài)。

  所以他建議在這里判斷recv函數(shù)的返回值是否已出錯,是的話就主動closesocket,這樣防止沒有接收到FIN包。

  因?yàn)榍懊嫖覀円呀?jīng)設(shè)置了recv超時(shí)時(shí)間為30秒,那么如果真的是超時(shí)了,這里收到的錯誤應(yīng)該是WSAETIMEDOUT,這種情況下也可以主動關(guān)閉連接的。

  還有一個問題,為什么有數(shù)千個連接都處于這個狀態(tài)呢?難道那段時(shí)間內(nèi),服務(wù)器端總是主動拆除我們的連接嗎?

  不管怎么樣,我們必須防止類似情況再度發(fā)生!

  首先,我們要保證原來的端口可以被重用,這可以通過設(shè)置SO_REUSEADDR套接字選項(xiàng)做到:

  重用本地地址和端口

  以前我總是一個端口不行,就換一個新的使用,所以導(dǎo)致讓數(shù)千個端口進(jìn)入CLOSE_WAIT狀態(tài)。如果下次還發(fā)生這種尷尬狀況,我希望加一個限定,只是當(dāng)前這個端口處于CLOSE_WAIT狀態(tài)!

  在調(diào)用

  sockConnected = socket(AF_INET, SOCK_STREAM, 0);

  之后,我們要設(shè)置該套接字的選項(xiàng)來重用:

  /// 允許重用本地地址和端口:

  /// 這樣的好處是,即使socket斷了,調(diào)用前面的socket函數(shù)也不會占用另一個,而是始終就是一個端口

  /// 這樣防止socket始終連接不上,那么按照原來的做法,會不斷地?fù)Q端口。

  int nREUSEADDR = 1;

  setsockopt(sockConnected,

  SOL_SOCKET,

  SO_REUSEADDR,

  (const char*)&nREUSEADDR,

  sizeof(int));

  教科書上是這么說的:這樣,假如服務(wù)器關(guān)閉或者退出,造成本地地址和端口都處于TIME_WAIT狀態(tài),那么SO_REUSEADDR就顯得非常有用。

  也許我們無法避免被凍結(jié)在CLOSE_WAIT狀態(tài)永遠(yuǎn)不出現(xiàn),但起碼可以保證不會占用新的端口。

  其次,我們要設(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ù)的過程中(send()沒有完成,還有數(shù)據(jù)沒發(fā)送)而調(diào)用了closesocket(),以前我們一般采取的措施是“從容關(guān)閉”:

  因?yàn)樵谕顺龇?wù)或者每次重新建立socket之前,我都會先調(diào)用

  /// 先將雙向的通訊關(guān)閉

  shutdown(sockConnected, SD_BOTH);

  /// 安全起見,每次建立Socket連接前,先把這個舊連接關(guān)閉

  closesocket(sockConnected);

  我們這次要這么做:

  設(shè)置SO_LINGER為零(亦即linger結(jié)構(gòu)中的l_onoff域設(shè)為非零,但l_linger為0),便不用擔(dān)心closesocket調(diào)用進(jìn)入“鎖定”狀態(tài)(等待完成),不論是否有排隊(duì)數(shù)據(jù)未發(fā)送或未被確認(rèn)。這種關(guān)閉方式稱為“強(qiáng)行關(guān)閉”,因?yàn)樘捉幼值奶撾娐妨⒓幢粡?fù)位,尚未發(fā)出的所有數(shù)據(jù)都會丟失。在遠(yuǎn)端的recv()調(diào)用都會失敗,并返回WSAECONNRESET錯誤。

  在connect成功建立連接之后設(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));

  總結(jié)

  也許我們避免不了CLOSE_WAIT狀態(tài)凍結(jié)的再次出現(xiàn),但我們會使影響降到最小,希望那個重用套接字選項(xiàng)能夠使得下一次重新建立連接時(shí)可以把CLOSE_WAIT狀態(tài)踢掉。

  我的意思是:當(dāng)一方關(guān)閉連接后,另外一方?jīng)]有檢測到,就導(dǎo)致了CLOSE_WAIT的出現(xiàn),上次我的一個朋友也是這樣,他寫了一個客戶端和 APACHE連接,當(dāng)APACHE把連接斷掉后,他沒檢測到,出現(xiàn)了CLOSE_WAIT,后來我叫他檢測了這個地方,他添加了調(diào)用 closesocket的代碼后,這個問題就消除了。

  如果你在關(guān)閉連接前還是出現(xiàn)CLOSE_WAIT,建議你取消shutdown的調(diào)用,直接兩邊closesocket試試。

  另外一個問題:

  比如這樣的一個例子:

  當(dāng)客戶端登錄上服務(wù)器后,發(fā)送身份驗(yàn)證的請求,服務(wù)器收到了數(shù)據(jù),對客戶端身份進(jìn)行驗(yàn)證,發(fā)現(xiàn)密碼錯誤,這時(shí)候服務(wù)器的一般做法應(yīng)該是先發(fā)送一個密碼錯誤的信息給客戶端,然后把連接斷掉。

  如果把

  m_sLinger.l_onoff = 1;

  m_sLinger.l_linger = 0;

  這樣設(shè)置后,很多情況下,客戶端根本就收不到密碼錯誤的消息,連接就被斷了。

  出現(xiàn)CLOSE_WAIT的原因很簡單,就是某一方在網(wǎng)絡(luò)連接斷開后,沒有檢測到這個錯誤,沒有執(zhí)行closesocket,導(dǎo)致了這個狀態(tài)的實(shí)現(xiàn),這在TCP/IP協(xié)議的狀態(tài)變遷圖上可以清楚看到。同時(shí)和這個相對應(yīng)的還有一種叫TIME_WAIT的。

  另外,把SOCKET的SO_LINGER設(shè)置為0秒拖延(也就是立即關(guān)閉)在很多時(shí)候是有害處的。

  還有,把端口設(shè)置為可復(fù)用是一種不安全的網(wǎng)絡(luò)編程方法。

  能不能解釋請看這里

  http://blog.csdn.net/cqq/archive/2005/01/26/269160.aspx

  再看這個圖:

  斷開連接的時(shí)候,

  當(dāng)發(fā)起主動關(guān)閉的左邊這方發(fā)送一個FIN過去后,右邊被動關(guān)閉的這方要回應(yīng)一個ACK,這個ACK是TCP回應(yīng)的,而不是應(yīng)用程序發(fā)送的,此時(shí),被動關(guān)閉的一方就處于CLOSE_WAIT狀態(tài)了。如果此時(shí)被動關(guān)閉的這一方不再繼續(xù)調(diào)用closesocket,那么他就不會發(fā)送接下來的FIN,導(dǎo)致自己老是處于CLOSE_WAIT。只有被動關(guān)閉的這一方調(diào)用了closesocket,才會發(fā)送一個FIN給主動關(guān)閉的這一方,同時(shí)也使得自己的狀態(tài)變遷為LAST_ACK。

  比如被動關(guān)閉的是客戶端。。。

  當(dāng)對方調(diào)用closesocket的時(shí)候,你的程序正在

  int nRet = recv(s,....);

  if (nRet == SOCKET_ERROR)

  {// closesocket(s);return FALSE;}

  很多人就是忘記了那句closesocket,這種代碼太常見了。

  我的理解,當(dāng)主動關(guān)閉的一方發(fā)送FIN到被動關(guān)閉這邊后,被動關(guān)閉這邊的TCP馬上回應(yīng)一個ACK過去,同時(shí)向上面應(yīng)用程序提交一個ERROR,導(dǎo)致上面的SOCKET的send或者recv返回SOCKET_ERROR,正常情況下,如果上面在返回SOCKET_ERROR后調(diào)用了 closesocket,那么被動關(guān)閉的者一方的TCP就會發(fā)送一個FIN過去,自己的狀態(tài)就變遷到LAST_ACK.

  

看過close wait是什么的人還看了:

1.dos命令詳解 dos命令大全

2.路由器如何查看本機(jī)所開端口

3.大學(xué)英語六級翻譯預(yù)熱練習(xí)題和答案

4.Linux中netstat命令怎么用

5.Linux中rsh怎么遠(yuǎn)程使用shell命令

2816380