Compartilhar via


Windows Sockets: 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 byte. As outras questões que são abordadas nos artigos: Windows Sockets: bloqueio e Windows Sockets: converter 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 da regra

Diferentes arquiteturas de computador às vezes armazenam dados usando diferentes ordens de byte. Por exemplo, computadores baseadas em Intel armazenam dados na ordem inversa dos computadores Macintosh (Motorola). A ordem de byte da Intel, chamada "little endian", também é o inverso da ordem "big endian" do padrão de rede. A tabela a seguir explica esses termos.

Ordenação de byte big endian e little endian

ordenação de byte 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 de ordem de byte para dados enviados e recebidos pela rede, mas há situações em que é necessário converter as ordens de byte.

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, ao contrário dos dados que você está enviando para outro computador. Por exemplo, você poderá passar as portas e os endereços, e a rede deverá reconhecer.

  • O aplicativo para servidores com o qual a comunicação está estabelecida não é um aplicativo do MFC (e você não tem o código-fonte dele). Isso chamará conversões de ordem de byte se os dois computadores não compartilharem a mesma ordem de byte.

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

É possível evitar o trabalho de converter ordens de byte nas seguintes situações:

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

  • O servidor com o qual a comunicação está estabelecida é um aplicativo do MFC.

  • Você tem o código-fonte do servidor com o qual a comunicação está estabelecida, portanto, você poderá dizer explicitamente se deverá converter ordens de byte ou não.

  • É possível portar o servidor para MFC. Isso é bastante fácil de fazer, e o resultado geralmente será 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 nos aplicativos ou usando as funções de conversão de ordem de byte do Windows Sockets, você poderá tornar o 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 gravando um aplicativo que estabelecerá comunicação com aplicativos não MFC, como um servidor FTP, provavelmente será necessário gerenciar a troca de bytes, 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 será detalhado posteriormente neste artigo.

Observação

Quando a outra extremidade da comunicação não for um aplicativo do MFC, também será necessário evitar o fluxo de objetos C++ derivados de CObject na camada de arquivos porque o receptor não poderá manipulá-los. Consulte a nota em Windows Sockets: usar soquetes com arquivos.

Para obter mais informações sobre ordens de byte, consulte as especificações 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 objetoCSocket que usa uma camada de arquivos. 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 em que você está gravando um cliente que estabelece comunicação com um aplicativo de servidor não MFC e você não tem acesso ao código-fonte do servidor. Neste cenário, será necessário assumir que o servidor não MFC usa a ordem de byte 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 estabelecer comunicação tenha um protocolo determinado para um pacote de mensagem como o seguinte:

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

Em termos do MFC, isso seria expresso da seguinte forma:

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

   void Serialize(CArchive &ar);
};

Em C++, um struct é essencialmente o mesmo que uma classe. A estrutura Message pode ter funções membro, como a função membro Serialize 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 chama conversões de dados de ordem de byte porque há uma clara incompatibilidade entre a ordenação de byte do aplicativo para servidores não MFC em uma extremidade e o CArchive usado no aplicativo cliente do MFC na outra extremidade. O exemplo ilustra várias funções de conversão de ordem de byte que o Windows Sockets fornece. A tabela a seguir descreve essas funções.

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

Função Finalidade
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 for um aplicativo não MFC, evite fazer algo semelhante ao seguinte:

ar << pMsg;

em que pMsg é um ponteiro para um objeto C++ derivado da classe CObject. Isso enviará informações adicionais do MFC associadas aos objetos e o servidor não reconhecerá, como faz quando é um aplicativo do MFC.

Para saber mais, veja:

Confira também

Windows Sockets em MFC