Compartilhar via


Windows Sockets: exemplo de soquetes que usam arquivos mortos

Este artigo apresenta um exemplo de uso da classe CSocket. O exemplo emprega objetos CArchive para serializar dados por meio de um soquete. Observe que isto não é serialização de documentos de ou para um arquivo.

O exemplo a seguir ilustra como você usa o arquivo para enviar e receber dados por meio de objetos CSocket. O exemplo foi projetado para que duas instâncias do aplicativo (no mesmo computador ou em computadores diferentes na rede) troquem dados. Uma instância envia dados, que a outra instância recebe e reconhece. Qualquer um dos dois aplicativos pode iniciar uma troca e atuar como servidor ou como cliente para o outro aplicativo. A seguinte função é definida na classe de exibição do aplicativo:

void PacketSerialize(long nPackets, CArchive &arData, CArchive &arAck)
{
   BYTE bValue = 0;
   WORD nCopies = 0;

   if (arData.IsStoring())
   {
      CString strText;
      errno_t err;
      unsigned int number;

      for (int p = 0; p < nPackets; p++)
      {
         err = rand_s(&number);
         // if (err == 0)...
         bValue = (BYTE)(number % 256);

         err = rand_s(&number);
         // if (err == 0)...
         nCopies = (WORD)(number % 32000);

         // Send header information
         arData << bValue << nCopies;
         for (int c = 0; c < nCopies; c++)
         {
            // Send data
            arData << bValue;
         }

         strText.Format(_T("Sender sent packet %d of %d (Value = %d, Copies = %d)"),
                        p + 1, nPackets, (int)bValue, nCopies);

         // Send receipt string
         arData << strText;
         arData.Flush();

         // Receive acknowledgment
         arAck >> strText;
         // display it
         DisplayMessage(strText);
      }
   }
   else
   {
      CString strText;
      BYTE bCheck;

      for (int p = 0; p < nPackets; p++)
      {
         // Receive header information
         arData >> bCheck >> nCopies;
         for (int c = 0; c < nCopies; c++)
         {
            // Receive data
            arData >> bValue;
            if (bCheck != bValue)
            {
               AfxMessageBox(_T("Packet Failure"));
            }
         }

         // Receive receipt string and display it
         arData >> strText;
         DisplayMessage(strText);

         strText.Format(_T("Recipient received packet %d of %d (Value = %d, Copies = %d)"),
                        p + 1, nPackets, (int)bValue, nCopies);

         // Send acknowledgment
         arAck << strText;
         arAck.Flush();
      }
   }
}

O mais importante neste exemplo é que sua estrutura é paralela à de uma função do MFC Serialize. A função membro PacketSerialize consiste em uma instrução if com uma cláusula else. A função recebe duas referências CArchive como parâmetros: arData e arAck. Se o objeto de arquivar arData estiver definido para armazenamento (envio), o branch if será executado; caso contrário, se arData estiver definido para carregamento (recebimento), a função assumirá o branch else. Para obter mais informações sobre serialização no MFC, consulte Serialização.

Observação

O objeto de arquivo arAck é considerado o oposto de arData. Se arData for para enviar, arAck receberá, e a recíproca é verdadeira.

Para enviar, a função de exemplo faz loops um número especificado de vezes, cada vez gerando alguns dados aleatórios para fins de demonstração. Seu aplicativo obteria dados reais de alguma fonte, como um arquivo. O operador de inserção de arquivos arData (<<) é usado para enviar um fluxo de três partes consecutivas de dados:

  • Um "cabeçalho" que especifica a natureza dos dados (nesse caso, o valor da variável bValue e quantas cópias serão enviadas).

    Ambos os itens são gerados aleatoriamente neste exemplo.

  • O número especificado de cópias dos dados.

    O loop interno for envia bValue o número de vezes especificado.

  • Uma cadeia de caracteres chamada strText que o receptor exibe para o usuário.

Para receber, a função opera de forma similar, exceto que usa o operador de extração do arquivo (>>) para obter dados do arquivo. O aplicativo receptor verifica os dados recebidos, exibe a mensagem final "Recebido" e envia de volta uma mensagem que diz "Enviado" para o aplicativo de envio ser exibido.

Neste modelo de comunicação, a palavra "Recebido", a mensagem enviada na variável strText, destina-se à exibição na outra extremidade da comunicação. Portanto, ela especifica ao usuário receptor que um determinado número de pacotes de dados foram recebidos. O receptor responde com uma cadeia de caracteres semelhante que diz "Enviado", para exibição na tela do remetente original. O recebimento de ambas as cadeias de caracteres indica que ocorreu uma comunicação bem-sucedida.

Cuidado

Se você estiver escrevendo um programa cliente MFC para se comunicar com servidores estabelecidos (não MFC), não envie objetos C++ por meio do arquivo. A menos que o servidor seja um aplicativo MFC que entenda os tipos de objetos que você deseja enviar, ele não conseguirá receber e desserializar seus objetos. Um exemplo no artigo Windows Sockets: ordem de bytes mostra uma comunicação desse tipo.

Para obter mais informações, consulte Especificação do Windows Sockets: htonl, htons, ntohl, ntohs. Para obter mais informações, consulte também:

Confira também

Windows Sockets em MFC
CArchive::IsStoring
CArchive::operator <<
CArchive::operator >>
CArchive::Flush
CObject::Serialize