• <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 迷宮の未來 閱讀(3136) 評論(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根本就還沒有發送出去,所以對等端意識不到連接已經中斷。  回復  更多評論   

            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            導航

            統計

            常用鏈接

            留言簿(10)

            隨筆檔案

            文章檔案

            最新隨筆

            搜索

            積分與排名

            最新隨筆

            最新評論

            閱讀排行榜

            評論排行榜

            久久久久久久97| yy6080久久| 国产福利电影一区二区三区久久久久成人精品综合 | 91精品国产91久久| 久久国产一片免费观看| 亚洲综合伊人久久综合| 国产999精品久久久久久| 7777久久久国产精品消防器材| 久久国产精品无码HDAV | 国产精品久久久福利| 久久成人永久免费播放| 亚洲伊人久久成综合人影院 | 国产成人无码精品久久久久免费 | 久久久久一区二区三区| 久久久久亚洲精品中文字幕| 欧美成人免费观看久久| 国产亚洲精久久久久久无码AV| 婷婷综合久久中文字幕蜜桃三电影| 99久久无色码中文字幕| 久久人妻少妇嫩草AV蜜桃| 久久国产精品视频| 久久精品一本到99热免费| 免费无码国产欧美久久18| 欧美性大战久久久久久| 久久久久久免费一区二区三区| 亚洲乱码中文字幕久久孕妇黑人| 久久久久国产亚洲AV麻豆| 天天综合久久久网| 91精品国产乱码久久久久久 | 久久这里都是精品| 99久久国产亚洲高清观看2024| 97久久国产亚洲精品超碰热| 伊人久久综合精品无码AV专区| 亚洲精品视频久久久| 99久久香蕉国产线看观香| 久久人人添人人爽添人人片牛牛 | 大伊人青草狠狠久久| 草草久久久无码国产专区| 久久国产精品波多野结衣AV| 久久国产午夜精品一区二区三区| 久久精品无码一区二区三区免费|