<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    weidagang2046的專欄

    物格而后知致
    隨筆 - 8, 文章 - 409, 評論 - 101, 引用 - 0
    數據加載中……

    配置Csocket 操作的超時時間

    察看本文應用于的產品
    文章編號 : 138692
    最后修改 : 2005年8月24日
    修訂 : 1.1
    本文的發布號曾為 CHS138692
    本頁

    概要

    更多信息

    BOOL SetTimeOut(UINT uTimeOut)

    BOOL KillTimeOut()

    BOOL OnMessagePending()

    示例代碼

    參考
    概要
    CSocket 操作,如“接收”(Receive)、“發送”(Send) 和“連接”(Connect) 均是阻塞操作,即要等到操作成功執行完畢或套接字上出現錯誤后,對這些函數的調用才有返回結果。

    在某些情況下,操作可能永遠不能成功完成,這將導致程序無限循環等待操作完成。一種解決方法是通過編程限制完成操作使用的時間。本文將討論這種方法。
    ?回到頂端

    更多信息
    這種方法是設置定時,讓它在操作時間過長時啟動。此方法的關鍵在于處理定時器的方式。雖然操作是“阻塞的”,但仍然可以處理到達的消息。如果通過使用 SetTimer 設置定時器,那么可以查找 WM_TIMER 消息,并在收到該消息時終止操作。該過程中涉及的主要函數有:
    Windows API 調用函數:
    ::SetTimer
    MFC 函數:
    CSocket::OnMessagePending
    CSocket::CancelBlockingCall
    為簡單起見,可以在 Csocket 衍生類中封裝該功能。

    警告:在進一步閱讀本文之前,請注意在某些 MFC 版本中存在錯誤,會在試圖使用定時器并重疊 OnMessagePending 時引起問題。這一問題將在下面的 Microsoft Knowledge Base 文章中進行討論:
    137632 (http://support.microsoft.com/kb/137632/EN-US/) 錯誤:定時器激活時未調用 OnMessagePending
    本文僅適用于 Visual C++ 的 1.52、1.52b、2.1 和 2.2 版本。如果使用的是這些 Visual C++ 版本之一,則還需要實施所提供的變通解決方法。

    本文最后部分顯示提供這種超時功能的類的示例代碼。以下內容講述由該類實現的函數。
    ?回到頂端

    BOOL SetTimeOut(UINT uTimeOut)


    調用此函數之后僅接著調用 CSocket 函數(如 Receive、Send 和 Accept)。uTimeOut 參數是以毫秒為單位指定的。之后,進行定時器的設置。如果設置定時器失敗,那么函數返回 FALSE。有關詳細情況,請參閱 SetTimer 函數的 Windows API 文檔。
    ?回到頂端

    BOOL KillTimeOut()


    在完成阻塞操作后,必須調用此函數。此函數刪除用 SetTimeOut 設置的定時器。如果調用 KillTimer 失敗,則返回 FALSE。有關詳細情況,請參閱 KillTimer 函數的 Windows API 文檔。
    ?回到頂端

    BOOL OnMessagePending()


    這是一個虛擬回調函數,在等待操作完成時由 CSocket 類進行調用。此函數給您提供處理傳入消息的機會。此實施過程檢查用 SetTimeOut 調用函數設置的定時器的 WM_TIMER 消息。如果收到消息,則調用 CancelBlockingCall 函數。有關 OnMessagePending 和 CancelBlockingCall 函數詳細的信息,請參閱 MFC 文檔。請注意:調用 CancelBlockingCall 函數 將導致操作失敗,而且 GetLastError 函數返回 WSAEINTR(表示操作中斷)。

    下面是使用該類的一個例子:
    ?? ...
    ?? CTimeOutSocket sockServer;
    ?? CAcceptedSocket sockAccept;

    ?? sockServer.Create(777);
    ?? sockServer.Listen();

    ?? // Note the following sequence:
    ?? //? SetTimeOut
    ?? //?
    ?? //? KillTimeOut

    ?? if(!sockServer.SetTimeOut(10000))
    ?? {
    ???? ASSERT(FALSE);
    ???? // Error Handling...for some reason, we could not setup
    ???? // the timer.
    ?? }

    ?? if(!sockServer.Accept(sockAccept))
    ?? {
    ???? int nError = GetLastError();
    ???? if(nError==WSAEINTR)
    ?????? AfxMessageBox("No Connections Arrived For 10 Seconds");
    ????? else
    ??????? ; // Do other error processing.
    ?? }

    ?? if(!sockServer.KillTimeOut())
    ?? {
    ???? ASSERT(FALSE);
    ???? // Error Handling...for some reason the timer could not
    ???? // be destroyed...perhaps a memory overwrite has changed
    ???? // m_nTimerID?
    ???? //
    ?? }
    ?? ...
    ?回到頂端

    示例代碼

    ?

    ?? //
    ?? // HEADER FILE
    ?? //
    ?? class CTimeOutSocket : public CSocket
    ?? {
    ?? public:
    ???? BOOL SetTimeOut(UINT uTimeOut);
    ???? BOOL KillTimeOut();
    ?? protected:
    ???? virtual BOOL OnMessagePending();
    ?? private:
    ???? int m_nTimerID;
    ?? };
    ?? //
    ?? // END OF FILE
    ?? //


    ?? //
    ?? // IMPLEMENTATION FILE
    ?? //
    ?? BOOL CTimeOutSocket::OnMessagePending()
    ?? {
    ???? MSG msg;
    ???? if(::PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE))
    ???? {
    ?????? if (msg.wParam == (UINT) m_nTimerID)
    ?????? {
    ???????? // Remove the message and call CancelBlockingCall.
    ???????? ::PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE);
    ???????? CancelBlockingCall();
    ???????? return FALSE;? // No need for idle time processing.
    ?????? };
    ???? };

    ???? return CSocket::OnMessagePending();
    ?? }

    ?? BOOL CTimeOutSocket::SetTimeOut(UINT uTimeOut)
    ?? {
    ???? m_nTimerID = SetTimer(NULL,0,uTimeOut,NULL);
    ???? return m_nTimerID;
    ?? }

    ?? BOOL CTimeOutSocket::KillTimeOut()
    ?? {
    ???? return KillTimer(NULL,m_nTimerID);
    ?? }
    CSOCKET的超時設置和UDP發送接收
    ??? 使用CSoket多次了,但對于它的block模式的理解并不是很深入。昨天使用csoket的udp多發測試(server接到數據后,需要通過某種方式將數據發送到client,使用tcp方式比較可靠,我一直這樣用的,但是比較費時,需要逐一發送),發現了問題:

    ? 1)create(),sendto(),receivefrom()....

    ? 2)其中,發送方一直定時發送數據無問題;

    ? 3)而接收方,通過一個單獨的接收線程實現( 注意:csocket不能跨線程使用!主線程中socket create()后,detach()并將sock作為lpvoid傳入接收線程 )。代碼如下:

    ? //處理接收數據
    UINT CSockSvr::DealSvrRevData(LPVOID lParam)
    {

    ? ......
    ?DWORD dwError;
    ?TCHAR cBuff[1000];
    ?CString sIP;
    ?UINT uPort;
    ?for(;!pDlg->m_bExit;)
    ?{
    ? ::memset( cBuff,0,sizeof(cBuff) );

    ? // 如果沒有接到數據,一直等待。。。。
    ? // 阻塞模式的弊端:::在退出時候,通過CancelBlockingCall
    ?? int iRst=SockSvr.ReceiveFrom( cBuff,sizeof(cBuff),sIP,uPort,0 );
    ??? if( iRst!=SOCKET_ERROR )
    ? {
    ?? CString sTemp=cBuff;
    ?? TRACE1( _T("\r\n Rev Data: %s\r\n"),sTemp );
    ? }
    ? else
    ? {
    ?? dwError=GetLastError();
    ?? TRACE1( _T("\r\n Rev Data Error code: %d\r\n"),dwError );
    ? }
    ? ::Sleep(200);
    ?}
    ?
    ?return 0;
    }

    ? 問題:如果發送方沒有數據,SockSvr.ReceiveFrom()會一致處于等待狀態,導致整個處理接收線程的停止,如果用戶需要退出/結束程序,無法正確釋放資源(無法關閉在線程函數重打開的socket--不能跨線程操作socket,無法關閉線程),造成系統memory leak...

    ? 針對這種問題,微軟的解決辦法是:http://support.microsoft.com/default.aspx?scid=kb;zh-cn;138692 ,經過測試,在socket進行connect()的時候不好用。后來,結合微軟的辦法,我通過自定義的定時器,實現了block超時間后自動退出的功能〉

    ? #if !defined(AFX_TIMEOUTSOCK_H__19897A81_4EAF_4005_91FD_DC3047725139__INCLUDED_)
    #define AFX_TIMEOUTSOCK_H__19897A81_4EAF_4005_91FD_DC3047725139__INCLUDED_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // TimeOutSock.h : header file
    //

    /*
    CSocket 操作,如接收(Receive)、發送(Send) 和連接(Connect) 均是阻塞操作,
    ?即要等到操作成功執行完畢或套接字上出現錯誤后,對這些函數的調用才有返回結果。
    某些情況下,操作可能永遠不能成功完成,這將導致程序無限循環等待操作完成。
    ?一種解決方法是通過編程限制完成操作使用的時間。本文將討論這種方法。
    */
    /////////////////////////////////////////////////////////////////////////////
    // CTimeOutSock command target

    class CTimeOutSock : public CSocket
    {
    // Attributes
    public:

    // Operations
    public:
    ?CTimeOutSock();
    ?virtual ~CTimeOutSock();

    // Overrides
    public:
    ?// ClassWizard generated virtual function overrides
    ?//{{AFX_VIRTUAL(CTimeOutSock)
    ?public:
    ?virtual BOOL OnMessagePending();
    ?//}}AFX_VIRTUAL

    ?// Generated message map functions
    ?//{{AFX_MSG(CTimeOutSock)
    ? // NOTE - the ClassWizard will add and remove member functions here.
    ?//}}AFX_MSG

    /*
    //定時器設置block超時 不是很好用。。。徐衛話 2006.4.19
    CSocket 操作,如接收(Receive)、發送(Send) 和連接(Connect) 均是阻塞操作,
    ?即要等到操作成功執行完畢或套接字上出現錯誤后,對這些函數的調用才有返回結果。
    某些情況下,操作可能永遠不能成功完成,這將導致程序無限循環等待操作完成。
    ?一種解決方法是通過編程限制完成操作使用的時間。本文將討論這種方法。
    */
    // 自己計算時間的辦法 OK
    public:
    ???? BOOL SetTimeOut(UINT uTimeOut=1000);
    ???? BOOL KillTimeOut();
    private:
    ? LONGLONG m_llDtStart;
    ? UINT? m_uTimeOut;
    };

    /////////////////////////////////////////////////////////////////////////////

    //}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.

    #endif // !defined(AFX_TIMEOUTSOCK_H__19897A81_4EAF_4005_91FD_DC3047725139__INCLUDED_)


    ? // TimeOutSock.cpp : implementation file
    //

    #include "stdafx.h"
    #include "NetBroad.h"
    #include "TimeOutSock.h"

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif

    /////////////////////////////////////////////////////////////////////////////
    // CTimeOutSock

    CTimeOutSock::CTimeOutSock()
    {

    }

    CTimeOutSock::~CTimeOutSock()


    // Do not edit the following lines, which are needed by ClassWizard.
    #if 0
    BEGIN_MESSAGE_MAP(CTimeOutSock, CSocket)
    ?//}AFX_MSG_MAP
    END_MESSAGE_MAP()
    #endif // 0

    /////////////////////////////////////////////////////////////////////////////
    // CTimeOutSock member functions

    //設置超時
    BOOL CTimeOutSock::SetTimeOut(UINT uTimeOut)
    {??
    ?//get start cnt
    ?LARGE_INTEGER llCnt;
    ?::QueryPerformanceCounter(&llCnt);
    ?m_llDtStart=llCnt.QuadPart;
    ?m_uTimeOut=uTimeOut;

    ???? return TRUE;
    }

    //刪除超時參數
    BOOL CTimeOutSock::KillTimeOut()
    {
    ?m_llDtStart=0;//表明取消計時
    ?return TRUE;
    }

    //檢查是否超時間
    BOOL CTimeOutSock::OnMessagePending()
    {
    ?// TODO: Add your specialized code here and/or call the base class
    ?/*
    ?MSG msg;
    ? if(::PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE))
    ? {
    ?? if (msg.wParam == (UINT) m_nTimerID)
    ?? {
    ??? // Remove the message and call CancelBlockingCall.
    ??? ::PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE);
    ??? CancelBlockingCall();
    ??? return FALSE;? // No need for idle time processing.
    ?? };
    ? };
    ?*/
    ?if( m_llDtStart )
    ?{
    ? LARGE_INTEGER lldtEnd;
    ? ::QueryPerformanceCounter(&lldtEnd);?
    ? LARGE_INTEGER llFrq;
    ? ::QueryPerformanceFrequency(&llFrq);
    ? double dbDealy=(double)(lldtEnd.QuadPart-m_llDtStart)*1000/llFrq.QuadPart;
    ? if( dbDealy>m_uTimeOut )
    ? {
    ?? CancelBlockingCall();
    ?? return FALSE;? // No need for idle time processing.
    ? }
    ?}
    ?
    ?return CSocket::OnMessagePending();
    }

    ?

    ? 經過改進后, 對處理接收線成的函數進行了部分改進:

    ? SockSvr.SetTimeOut(500);? int iRst=SockSvr.ReceiveFrom( cBuff,sizeofcBuff),sIP,uPort,0 );? SockSvr.KillTimeOut();

    ?當block超過定時后,socket自動退出block,防止接收線程停止。問題終于解決了!

    from: http://www.arm8.com/cv/1/6/197.html

    posted on 2006-11-06 00:16 weidagang2046 閱讀(5088) 評論(1)  編輯  收藏 所屬分類: Windows

    評論

    # Seoclick  回復  更多評論   

    Greeting. Seize opportunity by the beard, for it is bald behind.
    I am from Cyprus and , too, and now am writing in English, tell me right I wrote the following sentence: "While obviously not meant in any serious manner, the joke reminds me of my attitude towards seo, or “search engine optimization”.Offers search engine optimisation, web promotion and internet marketing services."

    :-( Thanks in advance. Grania.
    2009-05-18 20:44 | Seoclick
    主站蜘蛛池模板: 亚洲人成电影青青在线播放| 亚洲欧洲日韩在线电影| 国产亚洲无线码一区二区| 国产亚洲婷婷香蕉久久精品| 亚洲电影免费在线观看| 亚洲videosbestsex日本| 色天使亚洲综合一区二区| 特级毛片在线大全免费播放| 免费av片在线观看网站| 青青在线久青草免费观看| 麻豆国产精品入口免费观看| 亚洲人成无码久久电影网站| 亚洲福利在线观看| 亚洲中文字幕久久精品蜜桃| 麻豆一区二区三区蜜桃免费| 久久免费线看线看| 无码免费午夜福利片在线 | 在线免费观看你懂的| 国产一精品一AV一免费孕妇 | 可以免费看的卡一卡二| 可以免费观看一级毛片黄a| 亚洲AV无码成人精品区天堂 | 亚洲AV日韩AV无码污污网站| 久久久久免费视频| 可以免费看的卡一卡二| 精品国产人成亚洲区| 亚洲国产视频一区| 一级特黄a免费大片| 精品国产无限资源免费观看| 亚洲av成人一区二区三区在线观看| 亚洲av永久无码精品表情包| 亚洲欧洲无卡二区视頻| 免费a级毛片无码a∨免费软件 | 秋霞人成在线观看免费视频| 国内自产少妇自拍区免费| 亚洲不卡中文字幕无码| 亚洲av最新在线观看网址| 久9久9精品免费观看| 一本色道久久88亚洲综合| 亚洲国产成人无码av在线播放| 一级做a爰片久久毛片免费看 |