• <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>

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運轉,開心的工作
            簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            編寫大容量和健壯的服務器系列—處理IOCP連接關閉  2007-08-11 14:45

            分類:默認分類
            字號: ? ?

            ?

            ?

            鄧立波 深圳,2007-8

            作者聯系方式 :

            email: ???????? libodeng@gmail.com

            msn:? ???????? libodeng@gmail.com

            tel:???? ???????? 13510275799

            版權/著作權所有 (C) 2007 鄧立波 保留所有權利

            警告:未經作者許可,任何人或組織不得轉載,公開發布,拷貝,傳播本文獻的全部或部分

            ??

            及時監測連接被動關閉

            ?????? 除非有特別要求,否則你應該總是對每個連接保持一個掛起的接收 pending io

            (使用 WSARecv 投遞)。如果用戶主動關閉連接,你的 GetQueuedCompletionStatus 調用將返回成功,但接收到的數據長度為 0 ,你能根據這點檢測連接是否已被對方關閉。如果連接被重置或者 io 被取消(如果你調用了 CancelIo 的話), GetQueuedCompletionStatus 將返回失敗,注意這時還應該判斷 GetQueuedCompletionStatus 調用返回的 lpOverlapped 值,如果該值不為 NULL ,說明 iocp 已經檢測到一個連接已經中斷。

            ?

            安全的關閉連接

            ?????? 很多人寫的服務器網絡庫有一個難以接受的缺陷(包括我曾就職公司的一些同事),當服務器程序主動關閉連接時,剛發往客戶端的包有時出現丟失,這時他們推薦的方式往往是發送數據后等待幾秒再關閉連接。豪無疑問,這是一種笨拙的實現方式,他們遇到的問題根源是什么呢?

            ?????? 在非 IOCP 模式網絡程序中,你只要簡單的調用 closesocket 函數就可以確保數據在操作系統釋放 socket 之前安全到達對方,但在 IOCP 模式下,如果調用 closesocket 時有未決的 pending IO 將導致 socket 被重置,所以有時會出現數據丟失。正統的解決方式是使用 shutdown 函數(指定 SD_SEND 標志),注意這時可能有未完成的發送 pengding IO ,所以你應該監測是否該連接的所有是否已完成(也許你要用一個計數器來跟蹤這些 pending IO ),僅在所有 send pending IO 完成后調用 shutdown

            當你調用 shutdown 時,也許數據仍然停留在操作系統的緩沖,操作系統將在數據發送完后發出一個 FIN 包來啟動關閉進程,客戶端接收完數據后,將接受到一個 0 長度的包,以此判斷連接已關閉(你寫的客戶端肯定有檢測連接關閉,不是嗎?),然后調用 closesocket ,這時服務器的 GetQueuedCompletionStatus 將接收到一個數據長度為 0 的包,這時你就可以調用 closesocket ,并釋放相關連接資源。

            在絕大部分情況下上述的過程連接能完美的關閉。如果你特別注重服務器的安全性和健壯性,可能你還需要做一個“連接關閉隊列”,對每個已調用 shutdown 的連接放到這個隊列,然后定時的對這個隊列掃描,如果一個連接 5 秒(你也可以自己調整)還不能關閉,那么就強制關閉它。

            ?

            處理大并發短連接時如何避免 TIME_WAIT 狀態

            ?????? 關于如何避免 TIME_WAIT 這個問題,一直沒看到有效的處理方式(至少我沒有), 我將在這里披露一種有效的方式。回到上一段,我們最后調用了 closesocket 關閉連接,這時仍然可能出現 TIME_WAIT 狀態,但注意這時所有的數據都已經傳輸完畢,因此你可以強制關閉 socket 避免服務器連接進入 TIME_WAIT (這時只會發出連接重置 RESET 包)

            // 立即關閉 ( 避免出現 TIME_WAIT 狀態 )

            ?????? ?????? LINGER linger = {1,0};

            ?????? ?????? setsockopt(socket, SOL_SOCKET, SO_LINGER,

            ????????????? ?????? (char *)&linger, sizeof(linger));

            ?

            ?

            socket唯一性問題

            正常情況下 SOCKET 套結字值是唯一的,但是操作系統在分配 socket 值時有隨機性,最近關閉的 socket 值可能重新分派給一個剛剛建立的新的 socket. ,尤其在大并發短連接的情況下。一個健壯的服務器 IOCP 網絡庫必須要考慮 socket 唯一性的問題,由于 IOCP 的排隊機制,意味著當你調用 closesocket 關閉 socket 后, IOCP 隊列中可能仍然堆積了該 socket 的一些 I/O completion packet ,而此時,剛關閉的 socket 值又分派給一個剛剛建立的 socket ,所以,你必須對 GetQueuedCompletionStatus 獲取到的 I/O completion packet 小心翼翼處理,避免出現數據混亂,然而,最好的方式等到所有 I/O completion packet 返回后才調用 closesocket 關閉該 socket

            ?
            日本强好片久久久久久AAA| 狠色狠色狠狠色综合久久| yellow中文字幕久久网| 精品久久久久久久久午夜福利| 久久精品一区二区影院 | 精品久久久久国产免费| 久久夜色精品国产噜噜麻豆| 亚洲精品成人久久久| 久久精品亚洲精品国产欧美| 国产成人精品久久综合| 久久免费小视频| 国产91久久精品一区二区| 国内精品久久久久影院一蜜桃| 久久久无码精品亚洲日韩蜜臀浪潮 | 婷婷久久精品国产| 女同久久| 亚洲国产精品久久电影欧美| 亚洲国产精品无码成人片久久| 欧美喷潮久久久XXXXx| 无码人妻久久一区二区三区| 久久精品无码专区免费东京热| 国产精品久久久亚洲| 99精品久久久久久久婷婷| 国产亚洲精久久久久久无码AV| 久久国产视屏| 国产毛片欧美毛片久久久| 久久不见久久见免费视频7| 秋霞久久国产精品电影院| 久久久久无码中| 亚洲成色WWW久久网站| 精品久久无码中文字幕| 99久久99久久精品国产片果冻| 久久综合久久鬼色| 久久久老熟女一区二区三区| 久久夜色tv网站| 亚洲精品美女久久久久99小说| 亚洲精品国精品久久99热一| 日本道色综合久久影院| 99久久这里只精品国产免费| 久久精品国产亚洲AV高清热| 久久久久亚洲精品中文字幕 |