CSocket超时(Time-Out)功能的设置及其局限性

CSocket 是一个同步的socket类,如“接收”(Receive)、“发送”(Send) 和“连接”(Connect) 均是阻塞操作,即要等到操作成功执行完毕或套接字上出现错误后,对这些函数的调用才有返回结果。如果连接不上,只有超时以后才能返回。

在某些情况下,操作可能永远不能成功完成,这将导致程序无限循环等待操作完成。例如错误的域名解释,连接不上的IP地址,这回让用户等待近 40秒钟的时间(可能是默认的超时时间),而且等待期间,程序将会"假死", 如果这种情况频繁出现,软件就无法使用了。

微软MSDN上提供了一种解决方法:通过编程限制完成操作使用的时间。只要超过这个时间,无论是否成功都要返回。

示例代码:

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


   //
   // IMPLEMENTATION FILE
   //
   BOOL TimeOut_CSocket::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 TimeOut_CSocket::SetTimeOut(UINT uTimeOut)
   {
     m_nTimerID = SetTimer(NULL,0,uTimeOut,NULL);
     return m_nTimerID;
   }

   BOOL TimeOut_CSocket::KillTimeOut()
   {
     return KillTimer(NULL,m_nTimerID);
   }

 

 

 

有了这个CSocket的派生类后,就能自由设置 自己的 超时时间了,例如:

...
   TimeOut_CSocket 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?
     //
   }
   ...

这个方法经过测试还是有很大地局限性,当服务器联通时,确实能按照超时时间返回,但如果域名解释有问题或者ip地址连接不上,还是需要等待20s以上的超时时间。

要达到商业化软件的要求,我们推荐还是用专业的socket组件解决网络操作问题, 例如

糖果专业下载组件 就能做到 程序随时可以退出,永不"假死":

CSocket超时(Time-Out)功能的设置及其局限性

 

糖果专业下载组件 支持 多源 多线程下载, 支持各种代理,尤其是 能够穿透 局域网中的 ISA Server代理服务器(需要支持NTLM认证),做到IE能上网,软件就能上网。

 



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1763529


你可能感兴趣的:(socket)