• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴(yán)以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            TCP關(guān)閉連接(為什么會(huì)能Time_wait,Close_wait?)

            轉(zhuǎn)載自https://www.qcloud.com/community/article/102

            Tcp關(guān)閉連接問(wèn)題及注意

            最近一段時(shí)間一直在學(xué)習(xí)閱讀mina和nio的源碼,也發(fā)現(xiàn)了一些問(wèn)題無(wú)法解決,然后重讀了一下tcp協(xié)議,收獲頗多。(這就是帶著問(wèn)題去讀書(shū)的好處

            這次就和大家分享一下我們的netframework服務(wù)總會(huì)拋出一個(gè)“connet reset by peer”的原因吧。通過(guò)抓包工具分析,主動(dòng)關(guān)閉方直接發(fā)送了一個(gè)RST flags,而非FIN。就終止連接了。如下圖所示:

            為什么調(diào)用sokcet的close時(shí)只通過(guò)一次握手就終結(jié)連接了?

            要分析這個(gè)原因那就得從關(guān)閉連接程的四次握手,有時(shí)也會(huì)是三次握手,說(shuō)起。如下圖所示:

            大家都知道tcp正常的關(guān)閉連接要經(jīng)過(guò)四次握手。如下所示:

            在這四次握手狀態(tài)中,有一個(gè)特別要注意的狀態(tài)TIME_WAIT這個(gè)狀態(tài)是主動(dòng)關(guān)閉方在收到被關(guān)閉方的FIN后會(huì)處于并長(zhǎng)期(2個(gè)MSL時(shí)間,根據(jù)具體的實(shí)現(xiàn)不同,這個(gè)值會(huì)不同,在RFC 1122建議MSL=2分鐘,但在Berkeley的實(shí)現(xiàn)上使用的值為30s,具體可以看www.rfc.net ,要是沒(méi)有耐心去看英文的可以看這個(gè)網(wǎng)站www.cnpaf.net 里面有協(xié)議說(shuō)明以及相應(yīng)的源碼,java源碼中我沒(méi)有發(fā)現(xiàn)這個(gè)值,我只能追蹤到PlainSocketImpl.java這個(gè)類,再往下就是本地接口調(diào)用了,因此它是依賴本地操作系統(tǒng)的實(shí)現(xiàn))處于的一個(gè)狀態(tài)也就是大約1-4分鐘,然后由操作系統(tǒng)自動(dòng)回收并將TCP連接設(shè)為CLOSED初始狀態(tài)。如下圖所示:

            然而在socket的處于TIME_WAIT狀態(tài)之后到它結(jié)束之前,該socket所占用的本地端口號(hào)將一直無(wú)法釋放,因此服務(wù)在高并發(fā)高負(fù)載下運(yùn)行一段時(shí)間后,就常常會(huì)出現(xiàn)做為客戶端的程序無(wú)法向服務(wù)端建立新的socket連接的情況,過(guò)了1~4分鐘之后,客戶又可以連接上了,沒(méi)多久又連接不上,再等1~4分鐘之后又可以連接上,(上一個(gè)星期我們?cè)谧鲆粋€(gè)服務(wù)切換時(shí)遇到了這種情況)

            這是因?yàn)榉?wù)方socket資源已經(jīng)耗盡。netstat命令查看系統(tǒng)將會(huì)發(fā)現(xiàn)機(jī)器上存在大量處于TIME_WAIT狀態(tài)的socket連接,我這邊曾經(jīng)出現(xiàn)達(dá)到了2w多個(gè),并且占用大量的本地端口號(hào)。而此時(shí)機(jī)器上的可用本地端口號(hào)被占完,舊的大量處于TIME_WAIT狀態(tài)的socket尚未被系統(tǒng)回收時(shí),就會(huì)出現(xiàn)無(wú)法向服務(wù)端創(chuàng)建新的socket連接的情況。只能過(guò)2分鐘之后等系統(tǒng)回收這些socket和端口資源之后才能服務(wù),就這樣往復(fù)下去。

            TCP為什么要這么要讓這種TIME_WAIT狀態(tài)存活這么久呢?其原因有兩個(gè)(參考stevens的unix網(wǎng)絡(luò)編程卷1 第38頁(yè)):

            1. 可靠地實(shí)現(xiàn)TCP全雙工連接的終止。(確保最后的ACK能讓被關(guān)閉方接收)
            2. 允許老的重復(fù)分節(jié)在網(wǎng)絡(luò)中消逝。(TCP中是可靠的服務(wù),當(dāng)數(shù)據(jù)包丟失會(huì)重傳,當(dāng)有數(shù)據(jù)包迷路的情況下,如果不等待2MSL時(shí),當(dāng)客戶端以同樣地方式重新和服務(wù)建立連接后,上一次迷路的數(shù)據(jù)包這時(shí)可能會(huì)到達(dá)服務(wù),這時(shí)會(huì)造成舊包被重新讀取)

            解決方法:

            1、(推薦方法,只能治標(biāo)不治本)重用本地端口設(shè)置SO_REUSEADDR和SO_REUSEPORT(stevens的unix網(wǎng)絡(luò)編程卷1 第179~182頁(yè))有詳情的講解,這樣就可以允許同一端口上啟動(dòng)同一服務(wù)器的多個(gè)實(shí)例。怎樣理解呢?說(shuō)白了就是即使socket斷了,重新調(diào)用前面的socket函數(shù)不會(huì)再去占用新的一個(gè),而是始終就是一個(gè)端口,這樣防止socket始終連接不上,會(huì)不斷地?fù)Q新端口。Java 中通過(guò)調(diào)用Socket的setReuseAddress,詳細(xì)可以查看java.net.Socket源碼。【這個(gè)地方會(huì)有風(fēng)險(xiǎn),具體可以看(stevens的unix網(wǎng)絡(luò)編程卷1 第181頁(yè))

            2、修改內(nèi)核TIME_WAIT等待的值,如果客戶端和服務(wù)器都在同個(gè)路由器下,這個(gè)是非常推薦的。(鏈路好,重傳機(jī)率低)

            3、(不推崇,但目前我們是這樣做的,這個(gè)是造成(“connet reset by peer”)的元兇)設(shè)置SO_LINGER的值,java中是調(diào)用socket的 setSoLinger目前我們是設(shè)置為0的。設(shè)置為這個(gè)值的意思是當(dāng)主動(dòng)關(guān)閉方設(shè)置了setSoLinger(true,0)時(shí),并調(diào)用close后,立該發(fā)送一個(gè)RST標(biāo)志給對(duì)端,該TCP連接將立刻夭折,無(wú)論是否有排隊(duì)數(shù)據(jù)未發(fā)送或未被確認(rèn)。這種關(guān)閉方式稱為“強(qiáng)行關(guān)閉”,而后套接字的虛電路立即被復(fù)位,尚未發(fā)出的所有數(shù)據(jù)都會(huì)丟失。而被動(dòng)關(guān)閉方卻不知道對(duì)端已經(jīng)徹底斷開(kāi)。當(dāng)被動(dòng)關(guān)閉方正阻塞在recv()調(diào)用上時(shí),接受到RST時(shí),會(huì)立刻得到一個(gè)“connet reset by peer”的異常(即對(duì)端已經(jīng)關(guān)閉),c中是返回一個(gè)EPEERRST錯(cuò)。

            為什么不推崇這種方法在(stevens的unix網(wǎng)絡(luò)編程卷1 第173頁(yè))有詳細(xì)的講解。因?yàn)門IME_WAIT狀態(tài)是我們的朋友,它是有助有我們的(也就是說(shuō),它會(huì)讓舊的重復(fù)分節(jié)在網(wǎng)絡(luò)中超時(shí)消失(當(dāng)我們的鏈路越長(zhǎng),ISP復(fù)雜的情況下(從網(wǎng)通到教育網(wǎng)的ping包用了9000ms),重復(fù)的分節(jié)的比例是非常高的。))。而且我們主動(dòng)關(guān)閉連接方大都是由客戶端發(fā)起的(除了HTTP服務(wù)和異常),而且客戶方一般都不會(huì)有持續(xù)的大并發(fā)請(qǐng)求。 因此對(duì)資源沒(méi)有這么苛刻要求。

            轉(zhuǎn)載請(qǐng)注明出處: 騰云閣 https://www.qcloud.com/community

            posted on 2016-11-02 10:03 楊粼波 閱讀(982) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            国产 亚洲 欧美 另类 久久| 久久青草国产手机看片福利盒子| 久久久91精品国产一区二区三区| 国产精品久久久久久搜索| 久久久久久久精品成人热色戒| 日本高清无卡码一区二区久久| 久久国产精品99精品国产| 亚洲精品无码久久不卡| 国产精品成人99久久久久| 精品久久久久久久中文字幕| 国产A三级久久精品| 久久久久久久久久久| 久久久久国产成人精品亚洲午夜| 久久久久高潮综合影院| 久久国产欧美日韩精品| 久久精品国产精品亚洲精品| 久久这里有精品| 国产精品免费久久久久久久久| 亚洲午夜精品久久久久久app| 久久人人爽爽爽人久久久| 日韩精品久久无码人妻中文字幕 | 热99re久久国超精品首页| 久久久久亚洲av成人无码电影| 久久夜色撩人精品国产| 日韩精品久久久久久免费| 日产精品久久久一区二区| 国产美女久久精品香蕉69| 久久久久亚洲AV无码永不| 亚洲va中文字幕无码久久| 久久久久亚洲AV成人网人人网站 | 久久成人精品| 国内精品久久久久伊人av| 久久久久亚洲AV成人网人人网站 | 人妻无码中文久久久久专区| 亚洲人成网亚洲欧洲无码久久| 精品水蜜桃久久久久久久| 国产精品美女久久久久| 久久偷看各类wc女厕嘘嘘| 青青国产成人久久91网| 亚洲伊人久久成综合人影院| 亚洲日韩欧美一区久久久久我|