Artigo: 138692 - Última revisão: quinta-feira, 18 de Agosto de 2005 - Revisão: 1.3

Como configurar um limite de tempo na operação de 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 | Reduzir tudo

Sumário

Operações CSocket, tais como recepção, envio e ligar, são bloquear operações no sentido em que uma chamada para estas funções não irá devolver até foi concluída com êxito ou Ocorreu um erro no socket.

Em algumas circunstâncias, a operação pode nunca é concluída com êxito e o programa irá repetir sempre ao aguardar pela conclusão desta. Talvez seja boa ideia programaticamente limitar a quantidade de tempo permitido para a operação esteja concluída. Este artigo descreve uma forma de fazê-lo.

Mais Informação

Uma abordagem será definido um temporizador que é accionado quando a operação demorou demasiado tempo. A chave para esta abordagem é na forma como o temporizador é processado. Apesar da operação é "bloquear", ainda tem a capacidade para processar mensagens que chegam. Se definir um temporizador utilizando SetTimer, pode em seguida, procure a mensagem WM_TIMER e abortar a operação quando chegar. As funções principais envolvidas neste processo são:
A chamada de API do Windows:
:: SetTimer
As funções MFC:
CSocket::OnMessagePending
CSocket::CancelBlockingCall
Para uma questão de simplicidade, esta funcionalidade pode ser encapsulada na sua classe CSocket-derivado.

Aviso: Antes de ler mais, note que existe um erro em algumas versões do MFC que irá causar problemas se tentar utilizar um temporizador e substituir OnMessagePending. Este problema está documentado no seguinte artigo da base de dados de conhecimento da Microsoft:
137632  (http://support.microsoft.com/kb/137632/EN-US/ ) Erro: Não OnMessagePending chamada quando um temporizador de Active Directory
Este artigo aplica-se apenas a versões 1.52, 1.52b, 2.1 e 2.2 do Visual C++. Se estiver a utilizar uma destas versões do Visual C++, em seguida, também terá de implementar a solução é fornecida.

O código de exemplo para uma classe que fornece esta capacidade de limite de tempo está incluído no fim deste artigo. As funções implementadas pela classe são descritas nas secções seguintes deste artigo.

SetTimeOut(UINT uTimeOut) BOOL

Deve ser chamado imediatamente antes de chamar a função CSocket (por exemplo, receber, enviar entre aceitar). O parâmetro uTimeOut é especificado em milissegundos. Implementação que se segue configura simplesmente o temporizador. Esta função devolve FALSE se a tentativa para definir o temporizador falhou. Consulte a documentação da API do Windows sobre a função SetTimer para obter mais detalhes.

KillTimeOut() BOOL

Esta função tem de ser chamado após a conclusão da operação que estava a bloquear. Remove o temporizador foi configurado com SetTimeOut. Devolve FALSO se a chamada de KillTimer falhou. Consulte a documentação da API do Windows sobre a função KillTimer para obter mais detalhes.

OnMessagePending() BOOL

Esta é uma chamada de retorno virtual que é chamada pela classe CSocket quando está a aguardar uma operação seja concluída. Proporciona-lhe a oportunidade de fazer algo com mensagens a receber. Esta implementação verifica a mensagem WM_TIMER para o temporizador definido com a chamada SetTimeOut. E se chegar, em seguida, invoca a função CancelBlockingCall. Consulte a documentação do MFC sobre as funções OnMessagePending e CancelBlockingCall para obter detalhes. Note que, por chamada CancelBlockingCall, irá provocar a falha da operação e GetLastError devolverá WSAEINTR (indicando uma operação interrompida).

Eis um exemplo de utilização 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 mais informações sobre as funções SetTimer e KillTimer, consulte o ficheiro de ajuda de API do Windows.

Para mais informações sobre a classe CSocket e respectivas funções de membro, consulte:
Em 2.x do Visual C++ - O MFC ajuda ficheiro.
No Visual C++ 1,5 x - Mfcext.hlp O ficheiro de ajuda, que podem ser encontradas no CD no directó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 revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática? erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes 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 ArticleExclusão de Responsabilidade para Conteúdo sem Suporte na KB
Este artigo foi escrito sobre produtos para os quais a Microsoft já não fornece suporte. Por conseguinte, este artigo é oferecido "tal como está" e deixará de ser actualizado.