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

            對一個奇怪SOCKET問題的研究

               今天測試網絡服務程序時發現這樣一個現象:客戶端登錄到服務器,服務器如果驗證發現用戶名不存在,就返回客戶端錯誤信息,并斷開與客戶端的連接。但是實際測試時卻發現客戶端并沒有接收到用戶名不存在的錯誤信息,并且明明服務器端關閉了連接,甚至停止了服務,但是客戶端仍然顯示是連接狀態。

               調試,發現在斷開連接操作之前(即CLOSE SOCKET之前),加斷點或者寫LOG或者SLEEP幾毫秒后,客戶端都可接收到錯誤信息,并成功斷開。于是分析覺得問題可能出在SOCKET的IO處理上,可能SOCKET IO中的數據沒有足夠的時間完全發送,SOCKET就被關閉了。

               仔細檢查代碼發現CLOSE SOCKET前做了這樣的操作:

            LINGER lingerStruct;
            lingerStruct.l_onoff  = 1;    
            lingerStruct.l_linger = 0;
            setsockopt( IoSocket, SOL_SOCKET, SO_LINGER,    (char *)&lingerStruct, sizeof(lingerStruct) );
            CancelIo((HANDLE) IoSocket);
            closesocket( IoSocket );
               
               在MSDN中查找setsockeopt關于LINGER的解釋如下:

            Setting the SO_DONTLINGER option prevents blocking on member function Close while waiting for unsent data to be sent. Setting this option is equivalent to setting SO_LINGER with l_onoff set to 0.

                若設置了SO_LINGER,并設置了零超時間隔,則closesocket()不被阻塞立即執行,不論是否有排隊數據未發送或未被確認。這種關閉方式稱為“強制”或“失效”關閉,因為套接口的虛電路立即被復位,且丟失了未發送的數據。在遠端的recv()調用將以WSAECONNRESET出錯。
               若設置了SO_LINGER并確定了非零的超時間隔,則closesocket()調用阻塞進程,直到所剩數據發送完畢或超時。這種關閉稱為“優雅的”關閉。請注意如果套接口置為非阻塞且SO_LINGER設為非零超時,則closesocket()調用將以WSAEWOULDBLOCK錯誤返回。
               若在一個流類套接口上設置了SO_DONTLINGER,則closesocket()調用立即返回。但是,如果可能,排隊的數據將在套接口關閉前發送。請注意,在這種情況下WINDOWS套接口實現將在一段不確定的時間內保留套接口以及其他資源,這對于想用所以套接口的應用程序來說有一定影響。
              簡言之,setsockeopt函數使用SO_LINGER規定了斷開SOCKET時處理未發送完的數據的動作。


               查詢UNIX文檔中關于SO_LINGER參數的解釋更加詳細:

               SO_LINGER
               此選項指定函數close對面向連接的協議如何操作(如TCP)。缺省close操作是立即返回,如果有數據殘留在套接口緩沖區中則系統將試著將這些數據發送給對方。

            SO_LINGER選項用來改變此缺省設置。使用如下結構:
            struct linger {
                 int l_onoff; /* 0 = off, nozero = on */
                 int l_linger; /* linger time */
            };

            有下列三種情況:

            1. l_onoff為0,則該選項關閉,l_linger的值被忽略,等于缺省情況,close立即返回;
            2. l_onoff為非0,l_linger為0,則套接口關閉時TCP夭折連接,TCP將丟棄保留在套接口發送緩沖區中的任何數據并發送一個RST給對方,而不是通常的四分組終止序列,這避免了TIME_WAIT狀態;
            3. l_onoff 為非0,l_linger為非0,當套接口關閉時內核將拖延一段時間(由l_linger決定)。如果套接口緩沖區中仍殘留數據,進程將處于睡眠狀態,直 到(a)所有數據發送完且被對方確認,之后進行正常的終止序列(描述字訪問計數為0)或(b)延遲時間到。此種情況下,應用程序檢查close的返回值是 非常重要的,如果在數據發送完并被確認前時間到,close將返回EWOULDBLOCK錯誤且套接口發送緩沖區中的任何數據都丟失。close的成功返 回僅告訴我們發送的數據(和FIN)已由對方TCP確認,它并不能告訴我們對方應用進程是否已讀了數據。如果套接口設為非阻塞的,它將不等待close完 成。
            l_linger的單位依賴于實現,4.4BSD假設其單位是時鐘滴答(百分之一秒),但Posix.1g規定單位為秒。

               在了解了原理之后,將代碼中的lingerStruct.l_linger 設置為非零值,問題立即被解決。

               這里把這個問題寫出來,希望能夠給大家帶來點啟示。

            posted on 2007-11-14 11:45 迷宮の未來 閱讀(3140) 評論(6)  編輯 收藏 引用

            評論

            # re: 關閉SOCKET時需注意的問題[未登錄] 2007-11-14 15:45 heroboy

            shutdown(...) first.  回復  更多評論   

            # re: 關閉SOCKET時需注意的問題 2007-11-14 16:12 追夢時代

            @heroboy
            謝謝,剛測試了shutdown也可以解決問題  回復  更多評論   

            # re: 關閉SOCKET時需注意的問題 2007-11-14 16:21 追夢時代

            這里貼上MSDN對于shutdown的注意事項,shutdown不管SO_LINGER如何設置都不會堵塞。

            The shutdown function is used on all types of sockets to disable reception, transmission, or both.

            If the how parameter is SD_RECEIVE, subsequent calls to the recv function on the socket will be disallowed. This has no effect on the lower protocol layers. For TCP sockets, if there is still data queued on the socket waiting to be received, or data arrives subsequently, the connection is reset, since the data cannot be delivered to the user. For UDP sockets, incoming datagrams are accepted and queued. In no case will an ICMP error packet be generated.

            If the how parameter is SD_SEND, subsequent calls to the send function are disallowed. For TCP sockets, a FIN will be sent after all data is sent and acknowledged by the receiver.

            Setting how to SD_BOTH disables both sends and receives as described above.

            The shutdown function does not close the socket. Any resources attached to the socket will not be freed until closesocket is invoked.

            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.
            When FD_CLOSE received, call recv until zero returned, or SOCKET_ERROR.
            3. Call closesocket.

            Note The shutdown function does not block regardless of the SO_LINGER setting on the socket.

            An application should not rely on being able to reuse a socket after it has been shut down. In particular, a Windows Sockets provider is not required to support the use of connect on a socket that has been shut down.
              回復  更多評論   

            # re: 關閉SOCKET時需注意的問題 2007-11-14 16:34 追夢時代

            http://hi.baidu.com/developer_chen/blog/item/53208b4594f4bf25cefca322.html
            這篇文章描述了如何安全的關閉SOCKET  回復  更多評論   

            # re: 對一個奇怪SOCKET問題的研究 2007-12-23 17:21 秦歌

            shutdown管用  回復  更多評論   

            # re: 對一個奇怪SOCKET問題的研究 2008-01-31 22:00 abettor

            默認情況下,linger是保持TIME_WAIT狀態的。
            如果設置了linger選項,closesocket的時候就會以粗暴的形式實現。也就是,在斷開連接的三次握手時,一旦接受到了對方的ACK后,發送一個RST就立即清理資源,而并不等待TCP/IP協議棧真的將全部數據發出,更不會等上兩個MSL的TIME_WAIT狀態。這樣的話,也許RST根本就還沒有發送出去,所以對等端意識不到連接已經中斷。  回復  更多評論   

            <2007年11月>
            28293031123
            45678910
            11121314151617
            18192021222324
            2526272829301
            2345678

            導航

            統計

            常用鏈接

            留言簿(10)

            隨筆檔案

            文章檔案

            最新隨筆

            搜索

            積分與排名

            最新隨筆

            最新評論

            閱讀排行榜

            評論排行榜

            午夜久久久久久禁播电影| 久久精品人妻一区二区三区| 久久精品国产免费观看三人同眠| 欧美一级久久久久久久大| 免费无码国产欧美久久18| 久久99精品国产| 久久天天婷婷五月俺也去| 国产一久久香蕉国产线看观看 | 久久国产V一级毛多内射| 欧美伊人久久大香线蕉综合| 久久精品国产91久久综合麻豆自制| 国产精品VIDEOSSEX久久发布| 欧美日韩精品久久免费| 伊人久久综在合线亚洲2019| 久久精品国产亚洲AV久| 精品综合久久久久久88小说 | 色综合久久中文综合网| 97精品依人久久久大香线蕉97 | 97热久久免费频精品99| 国产精品美女久久福利网站| 久久久精品波多野结衣| 丁香五月综合久久激情| 国产精品免费看久久久| 久久亚洲AV成人无码软件| 久久久精品人妻无码专区不卡| 国产精品久久影院| 国产精品久久成人影院| 久久99精品久久久久久久不卡 | 久久精品亚洲精品国产欧美| 久久精品一区二区三区不卡| 婷婷伊人久久大香线蕉AV| 7777久久久国产精品消防器材| 久久婷婷国产剧情内射白浆| 国产精品久久久久久久久软件 | 国产免费久久精品99re丫y| 久久久久亚洲AV无码专区网站| 国产福利电影一区二区三区久久老子无码午夜伦不 | 欧洲性大片xxxxx久久久| 久久久噜噜噜久久| 亚洲欧洲精品成人久久奇米网| 久久一区二区三区99|