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

            lua

            如何優雅的關閉一個socket【轉】

            如何優雅地關閉一個socket 收藏

                最近在windows編程時需要考慮到“如何優雅地關閉一個socket”,查閱了一些資料,現將查到的相關資料做個匯編,希望能對后來者有所幫助(比較懶,所以英文資料沒有翻譯:-))

            1. 關閉Socket時究竟做了什么

                關閉socket分為主動關閉(Active closure)和被動關閉(Passive closure)兩種情況。前者是指有本地主機主動發起的關閉;而后者則是指本地主機檢測到遠程主機發起關閉之后,作出回應,從而關閉整個連接。
                其狀態圖如下圖所示:

               起初每個socket都是CLOSED狀態,當客戶端初使化一個連接,他發送一個SYN包到服務器,客戶端進入SYN_SENT狀態。
            服務器接收到SYN包,反饋一個SYN-ACK包,客戶端接收后返饋一個ACK包客戶端變成ESTABLISHED狀態,如果長時間沒收到SYN-ACK包,客戶端超時進入CLOSED狀態。
              當服務器綁定并監聽某一端口時,socket的狀態是LISTEN,當客戶企圖建立連接時,服務器收到一個 SYN包,并反饋SYN-ACK包。服務器狀態變成SYN_RCVD,當客戶端發送一個ACK包時,服務器socket變成ESTABLISHED狀態。

              當一個程序在ESTABLISHED狀態時有兩種圖徑關閉它, 第一是主動關閉,第二是被動關閉。如果你要主動關閉的話,發送一個FIN包。當你的程序closesocket或者shutdown(標記),你的程序發送一個FIN包到peer,你的socket變成FIN_WAIT_1狀態。peer反饋一個ACK包,你的socket進入FIN_WAIT_2狀態。如果peer也在關閉連接,那么它將發送一個FIN包到你的電腦,你反饋一個ACK包,并轉成TIME_WAIT狀態。
              TIME_WAIT狀態又號2MSL等待狀態。MSL意思是最大段生命周期(Maximum Segment Lifetime)表明一個包存在于網絡上到被丟棄之間的時間。每個IP包有一個TTL(time_to_live),當它減到0時則包被丟棄。每個路由器使TTL減一并且傳送該包。當一個程序進入TIME_WAIT狀態時,他有2個MSL的時間,這個充許TCP重發最后的ACK,萬一最后的ACK丟失了,使得FIN被重新傳輸。在2MSL等待狀態完成后,socket進入CLOSED狀態。
              被動關閉:當程序收到一個FIN包從peer,并反饋一個ACK包,于是程序的socket轉入CLOSE_WAIT狀態。因為peer已經關閉了,所以不能發任何消息了。但程序還可以。要關閉連接,程序自已發送給自已FIN,使程序的TCP socket狀態變成LAST_ACK狀態,當程序從peer收到ACK包時,程序進入CLOSED狀態。

            2. Winsock2 API中的相關函數

                先當然是查MSDN,看到winsocks2 API中的相關函數有:closesocket,shutdown,WSASendDisconnect. 我大致說一下,具體詳細的資料還請自行查MSDN.

                int closesocket( SOCKET s)的作用是關閉指定的socket,并且回收其所有的資源。
                int shutdown( SOCKET s,  int how)則是禁止在指定的socket s上禁止進行由how指定的操作,但并不對資源進行回收,shutdown之后而closesocket之前s還不能再次connect或者 WSAConnect.
                int WSASendDisconnect( SOCKET s,  LPWSABUF lpOutboundDisconnectData)則和shutdown基本類似,稍有不同的就是WSASendDisconnect函數多了一個lpOutboundDisconnectData參數,可以允許發送“斷開數據”(disconnect data).但MSDN上寫了“The native implementation of TCP/IP on Windows does not support disconnect data.”,所以一般我們就用shutdown函數就行了。


            3. Socket的優雅關閉

            在MSDN中對shutdown函數中的Remarks部分有下面一段話,指出了如何進行一次優雅的slcket關閉:

            To assure that all data is sent and received on a connected socket before it is closed, an application should use shutdown to close connection before calling closesocket. For example, to initiate a graceful disconnect:

               1. Call WSAAsyncSelect to register for FD_CLOSE notification.
               2. Call shutdown with how=SD_SEND.
               3. When FD_CLOSE received, call recv until zero returned, or SOCKET_ERROR.
               4. Call closesocket.

            closesocket的行為也是隨setsockopt()中參數的不同而有不同的表現,這里影響它的行為的主要就是那個linger結構。


            SO_DONTLINGER 若為真,則SO_LINGER選項被禁止。
            SO_LINGER 延遲關閉連接 struct linger
            上面這兩個選項影響close行為
            選項 間隔 關閉方式 等待關閉與否
            SO_DONTLINGER 不關心 優雅 否
            SO_LINGER 零 強制 否
            SO_LINGER 非零 優雅 是
            若設置了SO_LINGER(亦即 linger結構中的l_onoff域設為非零),并設置了零超時間隔,則closesocket()不被阻塞立即執行,不論是否有排隊數據未發送或未被確認。這種關閉方式稱為“強制”或“失效”關閉,因為套接口的虛電路立即被復位,且丟失了未發送的數據。在遠端的recv()調用將以 WSAECONNRESET出錯。
            若設置了SO_LINGER并確定了非零的超時間隔,則closesocket()調用阻塞進程,直到所剩數據發送完畢或超時。這種關閉稱為“優雅的”關閉。請注意如果套接口置為非阻塞且SO_LINGER設為非零超時,則closesocket()調用將以 WSAEWOULDBLOCK錯誤返回。
            若在一個流類套接口上設置了SO_DONTLINGER(也就是說將linger結構的l_onoff 域設為零),則closesocket()調用立即返回。但是,如果可能,排隊的數據將在套接口關閉前發送。請注意,在這種情況下WINDOWS套接口實現將在一段不確定的時間內保留套接口以及其他資源,這對于想用所以套接口的應用程序來說有一定影響。

                所以一般來說,不應該把linger設置為SO_LINGER 并且設置timeout為0,這樣的話,當本地主機調用closesocket時將會造成一個“強制”或“失效”的非優雅關閉。可以根據實際情況設置為另外兩種情況。

            posted on 2011-03-23 20:39 chib 閱讀(1220) 評論(0)  編輯 收藏 引用

            <2011年3月>
            272812345
            6789101112
            13141516171819
            20212223242526
            272829303112
            3456789

            導航

            統計

            常用鏈接

            留言簿(1)

            隨筆檔案

            牛人錄

            時政史料

            投資管理

            源碼庫

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            99久久精品国产一区二区三区| 99久久人妻无码精品系列| 91精品国产91热久久久久福利| 99久久久国产精品免费无卡顿| 国产Av激情久久无码天堂| 伊人久久免费视频| 国产99久久久国产精品小说| 久久棈精品久久久久久噜噜| 久久99国产精品久久99| 久久99精品久久久久久野外| 久久久久久久97| 国产午夜精品久久久久九九电影| 久久久一本精品99久久精品88| 91精品国产91久久综合| 色婷婷狠狠久久综合五月| 国产精品无码久久久久久| 久久夜色撩人精品国产小说| 久久久久久毛片免费播放| 国产精品午夜久久| avtt天堂网久久精品| 亚洲国产成人久久精品99| 国产午夜久久影院| 久久青青色综合| 国内精品欧美久久精品| 久久久久亚洲AV无码网站| 国产99久久久国产精品~~牛| 人妻无码αv中文字幕久久琪琪布| 精品国产一区二区三区久久蜜臀| 亚洲AV日韩精品久久久久| 青青久久精品国产免费看| 久久精品国产一区二区三区不卡| 99久久免费国产特黄| 久久ww精品w免费人成| 奇米影视7777久久精品| 7777精品久久久大香线蕉| 久久久久无码精品| 久久久久99精品成人片三人毛片| 精品乱码久久久久久夜夜嗨| 99久久精品这里只有精品 | 青青青青久久精品国产h久久精品五福影院1421| 国内高清久久久久久|