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

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

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

    weidagang2046的專欄

    物格而后知致
    隨筆 - 8, 文章 - 409, 評(píng)論 - 101, 引用 - 0
    數(shù)據(jù)加載中……

    配置Csocket 操作的超時(shí)時(shí)間

    察看本文應(yīng)用于的產(chǎn)品
    文章編號(hào) : 138692
    最后修改 : 2005年8月24日
    修訂 : 1.1
    本文的發(fā)布號(hào)曾為 CHS138692
    本頁

    概要

    更多信息

    BOOL SetTimeOut(UINT uTimeOut)

    BOOL KillTimeOut()

    BOOL OnMessagePending()

    示例代碼

    參考
    概要
    CSocket 操作,如“接收”(Receive)、“發(fā)送”(Send) 和“連接”(Connect) 均是阻塞操作,即要等到操作成功執(zhí)行完畢或套接字上出現(xiàn)錯(cuò)誤后,對(duì)這些函數(shù)的調(diào)用才有返回結(jié)果。

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

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

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

    本文最后部分顯示提供這種超時(shí)功能的類的示例代碼。以下內(nèi)容講述由該類實(shí)現(xiàn)的函數(shù)。
    ?回到頂端

    BOOL SetTimeOut(UINT uTimeOut)


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

    BOOL KillTimeOut()


    在完成阻塞操作后,必須調(diào)用此函數(shù)。此函數(shù)刪除用 SetTimeOut 設(shè)置的定時(shí)器。如果調(diào)用 KillTimer 失敗,則返回 FALSE。有關(guān)詳細(xì)情況,請(qǐng)參閱 KillTimer 函數(shù)的 Windows API 文檔。
    ?回到頂端

    BOOL OnMessagePending()


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

    下面是使用該類的一個(gè)例子:
    ?? ...
    ?? 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的超時(shí)設(shè)置和UDP發(fā)送接收
    ??? 使用CSoket多次了,但對(duì)于它的block模式的理解并不是很深入。昨天使用csoket的udp多發(fā)測(cè)試(server接到數(shù)據(jù)后,需要通過某種方式將數(shù)據(jù)發(fā)送到client,使用tcp方式比較可靠,我一直這樣用的,但是比較費(fèi)時(shí),需要逐一發(fā)送),發(fā)現(xiàn)了問題:

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

    ? 2)其中,發(fā)送方一直定時(shí)發(fā)送數(shù)據(jù)無問題;

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

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

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

    ? // 如果沒有接到數(shù)據(jù),一直等待。。。。
    ? // 阻塞模式的弊端:::在退出時(shí)候,通過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;
    }

    ? 問題:如果發(fā)送方?jīng)]有數(shù)據(jù),SockSvr.ReceiveFrom()會(huì)一致處于等待狀態(tài),導(dǎo)致整個(gè)處理接收線程的停止,如果用戶需要退出/結(jié)束程序,無法正確釋放資源(無法關(guān)閉在線程函數(shù)重打開的socket--不能跨線程操作socket,無法關(guān)閉線程),造成系統(tǒng)memory leak...

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

    ? #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)、發(fā)送(Send) 和連接(Connect) 均是阻塞操作,
    ?即要等到操作成功執(zhí)行完畢或套接字上出現(xiàn)錯(cuò)誤后,對(duì)這些函數(shù)的調(diào)用才有返回結(jié)果。
    某些情況下,操作可能永遠(yuǎn)不能成功完成,這將導(dǎo)致程序無限循環(huán)等待操作完成。
    ?一種解決方法是通過編程限制完成操作使用的時(shí)間。本文將討論這種方法。
    */
    /////////////////////////////////////////////////////////////////////////////
    // 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

    /*
    //定時(shí)器設(shè)置block超時(shí) 不是很好用。。。徐衛(wèi)話 2006.4.19
    CSocket 操作,如接收(Receive)、發(fā)送(Send) 和連接(Connect) 均是阻塞操作,
    ?即要等到操作成功執(zhí)行完畢或套接字上出現(xiàn)錯(cuò)誤后,對(duì)這些函數(shù)的調(diào)用才有返回結(jié)果。
    某些情況下,操作可能永遠(yuǎn)不能成功完成,這將導(dǎo)致程序無限循環(huán)等待操作完成。
    ?一種解決方法是通過編程限制完成操作使用的時(shí)間。本文將討論這種方法。
    */
    // 自己計(jì)算時(shí)間的辦法 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

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

    ???? return TRUE;
    }

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

    //檢查是否超時(shí)間
    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();
    }

    ?

    ? 經(jīng)過改進(jìn)后, 對(duì)處理接收線成的函數(shù)進(jìn)行了部分改進(jìn):

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

    ?當(dāng)block超過定時(shí)后,socket自動(dòng)退出block,防止接收線程停止。問題終于解決了!

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

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

    評(píng)論

    # Seoclick  回復(fù)  更多評(píng)論   

    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
    主站蜘蛛池模板: 日韩精品免费一线在线观看| 亚洲V无码一区二区三区四区观看| 亚洲国产成人久久一区WWW| 亚洲成A人片在线观看无码不卡 | 中文字幕久精品免费视频| 在线视频精品免费| 成人免费777777被爆出| 四虎成人免费大片在线| 亚洲国产成人片在线观看无码| 99国产精品免费观看视频| 亚洲阿v天堂在线2017免费| 未满十八18禁止免费无码网站| 美女被羞羞网站免费下载| 色www永久免费视频| 亚洲国产AV一区二区三区四区| 久久午夜羞羞影院免费观看| 午夜亚洲国产精品福利| 暖暖在线日本免费中文| 色欲aⅴ亚洲情无码AV| 亚洲av无码国产精品色在线看不卡| 99精品视频在线免费观看 | 一级毛片在线免费观看| 美女视频黄a视频全免费网站一区| 亚洲av午夜福利精品一区| 国产精品公开免费视频| 高潮毛片无遮挡高清免费视频| 亚洲欧洲日产国码www| 无码一区二区三区AV免费| 亚洲欧美日韩综合久久久| 日本视频免费在线| 无码专区永久免费AV网站| 无码人妻丰满熟妇区免费 | 性盈盈影院免费视频观看在线一区| 久久国产精品成人免费| 亚洲制服丝袜一区二区三区| 五月亭亭免费高清在线| 精品亚洲av无码一区二区柚蜜| 亚洲一卡2卡4卡5卡6卡残暴在线| 女人18毛片a级毛片免费视频| 成年人网站免费视频| 91九色老熟女免费资源站|