Partilhar via


Classe CSocket

Deriva de CAsyncSocket, herda seu encapsulamento da API do Windows Sockets e representa um nível mais alto de abstração do que o de um objeto CAsyncSocket.

Sintaxe

class CSocket : public CAsyncSocket

Membros

Construtores públicos

Nome Descrição
CSocket::CSocket Constrói um objeto CSocket.

Métodos públicos

Nome Descrição
CSocket::Attach Anexa um identificador SOCKET a um objeto CSocket.
CSocket::CancelBlockingCall Cancela uma chamada de bloqueio que esteja em andamento no momento.
CSocket::Create Cria um soquete.
CSocket::FromHandle Retorna um ponteiro para um objeto CSocket, dado um identificador de SOCKET.
CSocket::IsBlocking Determina se uma chamada de bloqueio está em andamento.

Métodos protegidos

Nome Descrição
CSocket::OnMessagePending Chamado para processar mensagens pendentes enquanto aguarda a conclusão de uma chamada de bloqueio.

Comentários

CSocket trabalha com as classes CSocketFile e CArchive para gerenciar o envio e o recebimento de dados.

Um objeto CSocket também fornece bloqueio, o que é essencial para a operação síncrona de CArchive. Funções de bloqueio, como Receive, Send, ReceiveFrom, SendTo e Accept (todas herdadas de CAsyncSocket), não retornam um erro WSAEWOULDBLOCK em CSocket. Em vez disso, essas funções esperam até que a operação seja concluída. Além disso, a chamada original terminará com o erro WSAEINTR se CancelBlockingCall for chamado enquanto uma dessas funções estiver bloqueando.

Para usar um objeto CSocket, chame o construtor e, em seguida, chame Create para criar o identificador SOCKET subjacente (tipo SOCKET). Os parâmetros padrão de Create criam um soquete de fluxo, mas se você não estiver usando o soquete com um objeto CArchive, poderá especificar um parâmetro para criar um soquete de datagram ou associar a uma porta específica para criar um soquete de servidor. Conecte-se a um soquete do cliente usando Connect no lado do cliente e Accept no lado do servidor. Em seguida, crie um objeto CSocketFile e associe-o ao objeto CSocket no construtor CSocketFile. Então, crie um objeto CArchive para enviar e outro para receber dados (conforme necessário) e associe-os ao objeto CSocketFile no construtor CArchive. Quando as comunicações forem concluídas, destrua os objetos CArchive, CSocketFile e CSocket. O tipo de dados SOCKET é descrito no artigo Windows Sockets: Segundo plano.

Quando você usa CArchive com CSocketFile e CSocket, pode encontrar uma situação em que CSocket::Receive insere um loop (por PumpMessages(FD_READ)) aguardando a quantidade solicitada de bytes. Isso ocorre porque os soquetes do Windows permitem apenas uma chamada recv por notificação FD_READ, mas CSocketFile e CSocket permitem várias chamadas recv por FD_READ. Se você receber um FD_READ quando não houver dados para ler, o aplicativo ficará travado. Se você nunca receber outro FD_READ, o aplicativo deixará de se comunicar pelo soquete.

Você pode resolver esse problema da seguinte maneira. No método OnReceive da classe de soquete, chame CAsyncSocket::IOCtl(FIONREAD, ...) antes de chamar o método Serialize da classe de mensagem quando os dados esperados a serem lidos do soquete excederem o tamanho de um pacote TCP (unidade de transmissão máxima do meio de rede, em geral, pelo menos 1096 bytes). Se o tamanho dos dados disponíveis for menor do que o necessário, aguarde até que todos os dados sejam recebidos e, somente em seguida, inicie a operação de leitura.

No exemplo a seguir, m_dwExpected é o número aproximado de bytes que o usuário espera receber. Supõe-se que você o declare em outro lugar em seu código.

void CChatSocket::OnReceive(int nErrorCode)
{
   CSocket::OnReceive(nErrorCode);

   DWORD dwReceived;

   if (IOCtl(FIONREAD, &dwReceived))
   {
      if (dwReceived >= m_dwExpected) // Process only if you have enough data
         m_pDoc->ProcessPendingRead();
   }
   else
   {
      // Error handling here
   }
}

Observação

Ao usar soquetes MFC em threads secundários em um aplicativo MFC vinculado estaticamente, você deve chamar AfxSocketInit em cada thread que usa soquetes para inicializar as bibliotecas de soquete. Por padrão, AfxSocketInit é chamado somente no thread primário.

Para obter mais informações, consulte Soquetes do Windows no MFC, Soquetes do Windows: usando soquetes com arquivos, Soquetes do Windows: como os soquetes com arquivos funcionam, Soquetes do Windows: sequência de operações, Soquetes do Windows: exemplo de soquetes usando arquivos.

Hierarquia de herança

CObject

CAsyncSocket

CSocket

Requisitos

Cabeçalho: afxsock.h

CSocket::Attach

Chame essa função membro para anexar o identificador hSocket a um objeto CSocket.

BOOL Attach(SOCKET hSocket);

Parâmetros

hSocket
Contém um identificador de um soquete.

Valor de retorno

Diferente de zero se a função for bem-sucedida.

Comentários

O identificador SOCKET é armazenado no membro de dados do objeto m_hSocket.

Para obter mais informações, consulte Soquetes do Windows: usando soquetes com arquivos.

Exemplo

class CSockThread : public CWinThread
{
public:
   SOCKET m_hConnected;

protected:
   CChatSocket m_sConnected;

   // remainder of class declaration omitted.

 

BOOL CSockThread::InitInstance()
{
   // Attach the socket object to the socket handle
   // in the context of this thread.
   m_sConnected.Attach(m_hConnected);
   m_hConnected = NULL;

   return TRUE;
}

 

// This listening socket has been constructed
// in the primary thread.
void CListeningSocket::OnAccept(int nErrorCode)
{
   UNREFERENCED_PARAMETER(nErrorCode);

   // This CSocket object is used just temporarily
   // to accept the incoming connection.
   CSocket sConnected;
   Accept(sConnected);

   // Start the other thread.
   CSockThread *pSockThread = (CSockThread*)AfxBeginThread(
       RUNTIME_CLASS(CSockThread), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
   if (NULL != pSockThread)
   {
      // Detach the newly accepted socket and save
      // the SOCKET handle in our new thread object.
      // After detaching it, it should no longer be
      // used in the context of this thread.
      pSockThread->m_hConnected = sConnected.Detach();
      pSockThread->ResumeThread();
   }
}

CSocket::CancelBlockingCall

Chame essa função membro para cancelar uma chamada de bloqueio atualmente em andamento.

void CancelBlockingCall();

Comentários

Essa função cancela qualquer operação de bloqueio pendente para este soquete. A chamada de bloqueio original será encerrada assim que possível com o erro WSAEINTR.

No caso de uma operação de bloqueio Connect, a implementação do Windows Sockets encerrará a chamada de bloqueio o mais rápido possível, mas pode não ser possível que os recursos do soquete sejam liberados até que a conexão seja concluída (e depois seja redefinida) ou atinja o tempo limite. Isso provavelmente será perceptível somente se o aplicativo tentar abrir imediatamente um novo soquete (se nenhum soquete estiver disponível) ou se conectar ao mesmo par.

Cancelar qualquer operação diferente de Accept pode deixar o soquete em um estado indeterminado. Se um aplicativo cancelar uma operação de bloqueio em um soquete, a única operação que o aplicativo pode depender de poder executar no soquete é uma chamada para Close, embora outras operações possam funcionar em algumas implementações do Windows Sockets. Se desejar portabilidade máxima para seu aplicativo, você deve ter cuidado para não depender da execução de operações após um cancelamento.

Para obter mais informações, consulte Soquetes do Windows: usando soquetes com arquivos.

CSocket::Create

Chame a função de membro Create depois de construir um objeto de soquete para criar o soquete do Windows e anexá-lo.

BOOL Create(
    UINT nSocketPort = 0,
    int nSocketType = SOCK_STREAM,
    LPCTSTR lpszSocketAddress = NULL);

Parâmetros

nSocketPort
Uma porta específica a ser usada com o soquete ou zero se você quiser que o MFC selecione uma porta.

nSocketType
SOCK_STREAM ou SOCK_DGRAM.

lpszSocketAddress
Um ponteiro para uma cadeia de caracteres que contém o endereço de rede do soquete conectado, um número separado por pontos, como "128.56.22.8". Passar a cadeia de caracteres NULL para esse parâmetro indica que a instância CSocket deve escutar a atividade do cliente em todas os interfaces de rede.

Valor de retorno

Diferente de zero se a função for bem-sucedida; caso contrário, 0 e um código de erro específico pode ser recuperado chamando GetLastError.

Comentários

Create em seguida chama Bind para associar o soquete ao endereço especificado. Há suporte para os seguintes tipos de soquete:

  • SOCK_STREAM Fornece fluxos de bytes baseados em conexão sequenciados, confiáveis e bidirecionais. Usa o protocolo TCP para a família de endereços na Internet.

  • SOCK_DGRAM Possui suporte para datagramas, que são pacotes sem conexão e não confiáveis de um comprimento máximo fixo (normalmente pequeno). Usa o UDP (User Datagram Protocol) para a família de endereços na Internet. Para usar essa opção, você não deve usar o soquete com um objeto CArchive.

    Observação

    A função membro Accept faz uma referência a um novo objeto CSocket vazio como seu parâmetro. Você deve construir esse objeto antes de chamar Accept. Tenha em mente que, se esse objeto de soquete ficar fora do escopo, a conexão será fechada. Não chame Create para esse novo objeto de soquete.

Para obter mais informações sobre soquetes de fluxo e datagrama, consulte os artigos Windows Sockets: Segundo plano, Windows Sockets: Endereços de portas e soquetes e Windows Sockets: usando soquetes com arquivos.

CSocket::CSocket

Constrói um objeto CSocket.

CSocket();

Comentários

Após a construção, você deve chamar a função membro Create.

Para obter mais informações, consulte Soquetes do Windows: usando soquetes com arquivos.

CSocket::FromHandle

Um ponteiro para um objeto CSocket.

static CSocket* PASCAL FromHandle(SOCKET hSocket);

Parâmetros

hSocket
Contém um identificador de um soquete.

Valor de retorno

Um ponteiro para um objeto CSocket, ou NULL se não houver nenhum objeto CSocket anexado a hSocket.

Comentários

Quando determinado um identificador SOCKET, se um objeto CSocket não estiver anexado ao identificador, a função membro retornará NULL e não criará um objeto temporário.

Para obter mais informações, consulte Soquetes do Windows: usando soquetes com arquivos.

CSocket::IsBlocking

Chame essa função membro para determinar se uma chamada de bloqueio está em andamento.

BOOL IsBlocking();

Valor de retorno

Diferente de zero se o soquete estiver bloqueando; caso contrário, zero.

Comentários

Para obter mais informações, consulte Soquetes do Windows: usando soquetes com arquivos.

CSocket::OnMessagePending

Substitua essa função membro para procurar mensagens específicas do Windows e responda a elas em seu soquete.

virtual BOOL OnMessagePending();

Valor de retorno

Diferente de zero se a mensagem tiver sido tratada; caso contrário, zero.

Comentários

Essa é uma substituição avançada.

A estrutura chama OnMessagePending enquanto o soquete está enviando mensagens do Windows para lhe dar a oportunidade de lidar com mensagens de interesse para seu aplicativo. Para obter exemplos de como você pode usar OnMessagePending, consulte o artigo Soquetes do Windows: Derivando de classes de soquete.

Para obter mais informações, consulte Soquetes do Windows: usando soquetes com arquivos.

Confira também

Classe CAsyncSocket
Gráfico da hierarquia
Classe CAsyncSocket
Classe CSocketFile