ID do artigo: 138692 - Última revisão: quinta-feira, 18 de agosto de 2005 - Revisão: 1.3

Como configurar um tempo limite em uma operação CSocket

Dica do SistemaEste artigo aplica-se a um sistema operativo diferente do que está a utilizar. Foi desactivado o conteúdo do artigo, que pode não ser relevante para si.

Nesta página

Expandir tudo | Recolher tudo

Sumário

CSocket operações, tais como receber, enviar e conectar-se, estão bloqueando operações no sentido de que uma chamada para essas funções não retornará até que ele foi concluída com êxito ou ocorreu um erro no soquete.

Em algumas circunstâncias, a operação nunca pode concluída com êxito e o programa será loop contínuo enquanto aguarda a essa conclusão. Talvez seja uma boa idéia programaticamente limitar a quantidade de tempo permitido para a conclusão da operação. Este artigo descreve uma maneira de fazê-lo.

Mais Informações

Uma abordagem seria definir um timer é acionado quando a operação levou muito tempo. A chave para essa abordagem é em como o timer é manipulado. Embora "bloquear" a operação, você ainda tem a capacidade de manipular as mensagens que chegam. Se você definir um timer usando SetTimer, você pode procurar a mensagem WM_TIMER e anular a operação quando ele chega. As funções principais envolvidas nesse processo são:
A chamada de API do Windows:
:: SetTimer
As funções MFC:
CSocket::OnMessagePending
CSocket::CancelBlockingCall
Para manter a simplicidade, essa funcionalidade pode ser encapsulada em sua classe derivada CSocket.

Aviso: Antes de ler ainda mais, observe que há um bug em algumas versões do MFC que causará problemas se você tentar usar um timer e substituir OnMessagePending. Esse problema está documentado no seguinte artigo Base de dados de Conhecimento Microsoft:
137632  (http://support.microsoft.com/kb/137632/EN-US/ ) Erro: Não OnMessagePending chamado quando um timer está ativo
Este artigo se aplica somente às versões 1.52, 1.52b, 2.1 e 2.2 do Visual C++. Se você estiver usando uma dessas versões do Visual C++, em seguida, você também precisará implementar a solução alternativa é fornecida.

O código de exemplo para uma classe que fornece esse recurso de tempo limite é incluído no final deste artigo. As funções implementadas pela classe são descritas nas seções a seguir deste artigo.

BOOL SetTimeOut(UINT uTimeOut)

Isso deve ser chamado imediatamente antes de chamar a função CSocket (por exemplo, receber, enviar e aceitar). O parâmetro uTimeOut é especificado em milissegundos. A seguinte implementação simplesmente configura o timer. Esta função retorna FALSO se Falha ao tentar definir o timer. Consulte a documentação da API do Windows sobre a função SetTimer para obter mais detalhes.

BOOL KillTimeOut()

Essa função precisa ser chamado após a conclusão da operação que foi bloqueio. Ele remove o timer que foi configurado com SetTimeOut. Ele retorna FALSO se a chamada para KillTimer falhou. Consulte a documentação da API do Windows sobre a função KillTimer para obter mais detalhes.

BOOL OnMessagePending()

Este é um retorno de chamada virtual que é chamado pela classe CSocket quando ele está aguardando a conclusão de uma operação. Ela lhe dá a oportunidade de fazer algo com mensagens de entrada. Essa implementação verifica a mensagem WM_TIMER para o timer com a chamada SetTimeOut. E se chegar, em seguida, ele chama a função CancelBlockingCall. Consulte a documentação do MFC sobre as funções OnMessagePending e CancelBlockingCall para obter detalhes. Observe que, por chamada CancelBlockingCall, fará com que a operação falhasse e GetLastError retornará WSAEINTR (indicando uma operação interrompida).

Aqui é um uso de exemplo desta classe:
   ...
   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?
     // 
   }
   ...
				

Código de exemplo

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

Referências

Para obter mais informações sobre as funções SetTimer e KillTimer, consulte o arquivo de Ajuda de API do Windows.

Para obter mais informações sobre a classe CSocket e suas funções de membro, consulte:
Em Visual C++ 2.x - O MFC arquivo de Ajuda.
Em Visual C++ 1.5 x - Mfcext.hlp O arquivo de Ajuda, que pode ser encontrada no CD no diretório \Msvc15\Help.

A informação contida neste artigo aplica-se a:
  • Microsoft Foundation Class Library 4.2
Palavras-chave: 
kbmt kbapi kbcode kbhowto kbnetwork kbtimer kbwinsock KB138692 KbMtpt
Tradução automáticaTradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 138692  (http://support.microsoft.com/kb/138692/en-us/ )
Retired KB ArticleAviso de Isenção de Responsabilidade sobre Conteúdo do KB Aposentado
Este artigo trata de produtos para os quais a Microsoft não mais oferece suporte. Por esta razão, este artigo é oferecido "como está" e não será mais atualizado.