欢迎访问:常州市武进区嘉泽中心小学网站 !今天是:
栏目列表
您现在的位置是:首页>>教师>>计算机技术>>程序设计>>杂项>>文章内容
为CSocket配置Time-Out功能
发布时间:2008-11-20   点击:   来源:本站原创   录入者:佚名
  为CSocket配置Time-Out功能     CSocket操作,如Send(),Receive(),Connect()都属阻塞操作,即它们在成功完成或错误发生之前是不会返回的。
    在某些情况下,某项操作可能永远不能成功完成,程序为了等待其完成就得永远循环下去。在程序中为某项操作限定一个成功完成的时间是个好主意。本文就是讨论此问题的。
    一个办法是设计一个计时器,当操作费时过长时就触发。这个办法的关键是怎样处理计时器。虽然操作是"阻塞"的,但仍具处理传回的消息的能力。如果用SetTimer来设置计时器,就可截获WM_TIMER消息,当它产生时就终止操作。涉及到这个过程的主要函数是:Windows API ::SetTimer(),MFC函数CSocket::OnMessagePending()和CSocket:: CancelBlockingCall()。这些功能可包装到你的CSocket类中得以简化。
    类中用到三个重要函数:
    BOOL SetTimeOut(UINT uTimeOut) 它应在CSocket函数调用前被调用。uTimeOut以千分秒为单位。下面的实现只是简单的设置计时器。当设置计时器失败时返回False。参见Windows API中关于SetTimer的说明。
    BOOL KillTimeOut() 此函数应在操作未完成被阻塞时被调用。它删除SetTimeOut所设置的计时器。如果调用KillTimer失败则返回False。参见Windows API中关于KillTimer的说明。
    BOOL OnMessagePending() 它是一个虚拟回调函数,当等待操作完成时被CSocket类调用。它给你机会来处理传回的消息。这次我们用它来检查SetTimeOut所设置的计时器,如果超时(Time-Out),则它调用CancelBlockingCall()。参见MFC文档关于OnMessagePending()和CancelBlockingCall()的说明。注意调用CancelBlockingCall()将使当前操作失败,GetLastError()函数返回WSAEINTR(指出是中断操作)。
    下面就是使用这个类的例子:
   ...

   CTimeOutSocket sockServer;

   CAcceptedSocket sockAccept;



   sockServer.Create(777);

   sockServer.Listen();



   // Note the following sequence:

   //  SetTimeOut

   //  <operation which might block>

   //  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);

   }


附件:
    关闭窗口
    打印文档
    账号登录
    保持登录 忘记密码?
    账号与武进教师培训平台同步