Compartilhar via


Soquetes do Windows: ordenação de bytes

Este artigo e dois artigos complementares explicam vários problemas na programação do Windows Sockets. Este artigo aborda a ordenação de bytes. Os outros problemas são abordados nos artigos: Soquetes do Windows: Bloqueio e Soquetes do Windows: Convertendo Cadeias de Caracteres.

Se você usar ou derivar da classe CAsyncSocket, precisará gerenciar esses problemas por conta própria. Se você usar ou derivar da classe CSocket, o MFC os gerenciará para você.

Ordenação de bytes

Arquiteturas de máquina diferentes às vezes armazenam dados usando pedidos de bytes diferentes. Por exemplo, computadores baseados em Intel armazenam dados na ordem inversa dos computadores Macintosh (Motorola). A ordem de bytes da Intel, chamada "little-Endian", também é o inverso da ordem padrão de rede "big-Endian". A tabela a seguir explica esses termos.

Ordenação de byte big endian e little endian

Ordenação de bytes Significado
Big endian O byte mais significativo está na extremidade esquerda de uma palavra.
Little endian O byte mais significativo está na extremidade direita de uma palavra.

Normalmente, você não precisa se preocupar com a conversão da ordem de bytes para os dados que envia e recebe pela rede, mas há situações em que é necessário converter a ordem dos bytes.

Quando é necessário converter a ordem de byte

É necessário converter as ordens de bytes nas seguintes situações:

  • Você está passando informações que precisam ser interpretadas pela rede, em vez dos dados que você está enviando para outro computador. Por exemplo, você pode passar portas e endereços, que a rede deve entender.

  • O aplicativo de servidor com o qual você está se comunicando não é um aplicativo MFC (e você não tem código-fonte para ele). Isso exige conversões de ordem de bytes se os dois computadores não compartilharem a mesma ordem de bytes.

Quando não é necessário converter ordem de byte

Você pode evitar o trabalho de conversão de ordem de bytes nas seguintes situações:

  • Os computadores em ambas as extremidades podem concordar em não trocar bytes e ambos os computadores usam a mesma ordem de bytes.

  • O servidor com o qual você está se comunicando é um aplicativo MFC.

  • Você tem o código-fonte do servidor com o qual está se comunicando, então pode determinar explicitamente se deve converter a ordem de bytes ou não.

  • Você pode portar o servidor para o MFC. Isso é bastante fácil de fazer, e o resultado geralmente é um código menor e mais rápido.

Ao trabalhar com CAsyncSocket, você mesmo deverá gerenciar todas as conversões de ordem de byte necessárias. O Windows Sockets padroniza o modelo de ordem de bytes "big-Endian" e fornece funções para converter entre essa ordem e outras. CArchive, no entanto, que você usa com CSocket, usa a ordem oposta ("little endian"), mas o CArchive cuidará dos detalhes das conversões de ordem de byte para você. Usando essa ordenação padrão em seus aplicativos ou usando funções de conversão de ordem de bytes do Windows Sockets, você pode tornar seu código mais portátil.

O caso ideal para usar soquetes do MFC é quando você está gravando em ambas as extremidades da comunicação: usando o MFC em ambas as extremidades. Se você estiver escrevendo um aplicativo que se comunicará com aplicativos não MFC, como um servidor FTP, provavelmente precisará gerenciar a troca de bytes por conta própria antes de passar os dados para o objeto de arquivo, usando as rotinas de conversão do Windows Sockets ntohs, ntohl, htons e htonl. Um exemplo dessas funções usadas na comunicação com um aplicativo não MFC é exibido posteriormente neste artigo.

Observação

Quando a outra extremidade da comunicação não é um aplicativo MFC, você também deve evitar transmitir objetos C++ derivados de CObject em seu arquivo, pois o receptor não será capaz de lidar com eles. Consulte a observação em Soquetes do Windows: Usando soquetes com arquivos.

Para obter mais informações sobre pedidos de bytes, consulte a especificação do Windows Sockets, disponível no SDK do Windows.

Um exemplo de conversão de ordem de byte

O exemplo a seguir mostra uma função de serialização para um objeto CSocket que usa um arquivo. Ilustra também o uso das funções de conversão de ordem de byte na API do Windows Sockets.

Este exemplo apresenta um cenário no qual você está escrevendo um cliente que se comunica com um aplicativo de servidor não MFC para o qual você não tem acesso ao código-fonte. Nesse cenário, você deve assumir que o servidor não MFC usa a ordem de bytes de rede padrão. Em contrapartida, o aplicativo cliente do MFC usa um objeto CArchive com um objeto CSocket, e CArchive usa ordem de byte "little endian", o oposto do padrão de rede.

Suponha que o servidor não MFC com o qual você planeja se comunicar tenha um protocolo estabelecido para um pacote de mensagens como o seguinte:

struct Message
{
   long MagicNumber;
   unsigned short Command;
   short Param1;
   long Param2;
};

Em termos MFC, isso seria expresso da seguinte maneira:

struct Message
{
   long m_lMagicNumber;
   short m_nCommand;
   short m_nParam1;
   long m_lParam2;

   void Serialize(CArchive &ar);
};

Em C++, uma struct é essencialmente a mesma coisa que uma classe. A Message estrutura pode ter funções de membro, como a Serialize função membro declarada acima. A função membro Serialize pode ter esta aparência:

void Message::Serialize(CArchive &ar)
{
   if (ar.IsStoring())
   {
      ar << (DWORD)htonl(m_lMagicNumber);
      ar << (WORD)htons(m_nCommand);
      ar << (WORD)htons(m_nParam1);
      ar << (DWORD)htonl(m_lParam2);
   }
   else
   {
      WORD w;
      DWORD dw;
      ar >> dw;
      m_lMagicNumber = ntohl((long)dw);
      ar >> w;
      m_nCommand = ntohs((short)w);
      ar >> w;
      m_nParam1 = ntohs((short)w);
      ar >> dw;
      m_lParam2 = ntohl((long)dw);
   }
}

Este exemplo exige conversões de ordem de bytes de dados porque há uma clara incompatibilidade entre a ordenação de bytes do aplicativo de servidor não MFC em uma extremidade e a CArchive usada em seu aplicativo cliente MFC na outra extremidade. O exemplo ilustra várias das funções de conversão de ordem de bytes fornecidas pelo Windows Sockets. A tabela a seguir descreve essas funções.

Funções de conversão de ordem de byte do Windows Sockets

Função Propósito
ntohs Converte uma quantidade de 16 bits da ordem de byte da rede para a ordem de byte do host (big endian para little endian).
ntohl Converte uma quantidade de 32 bits da ordem de byte da rede para a ordem de byte do host (big endian para little endian).
Htons Converte uma quantidade de 16 bits da ordem de byte do host para a ordem de byte da rede (little endian para big endian).
Htonl Converte uma quantidade de 32 bits da ordem de bytes do host para a ordem de byte da rede (little endian para big endian).

Outro ponto deste exemplo é que, quando o aplicativo de soquete na outra extremidade da comunicação é um aplicativo não MFC, você deve evitar fazer algo semelhante ao seguinte:

ar << pMsg;

onde pMsg é um ponteiro para um objeto C++ derivado da classe CObject. Isso enviará informações adicionais de MFC associadas a objetos e o servidor não o entenderá, como faria se fosse um aplicativo MFC.

Para obter mais informações, consulte:

Consulte também

Soquetes do Windows no MFC