Soquete Unix - Pedidos de Byte de Rede

Infelizmente, nem todos os computadores armazenam os bytes que constituem um valor multibyte na mesma ordem. Considere uma Internet de 16 bits composta por 2 bytes. Existem duas maneiras de armazenar esse valor.

  • Little Endian - Neste esquema, o byte de ordem inferior é armazenado no endereço inicial (A) e o byte de ordem superior é armazenado no próximo endereço (A + 1).

  • Big Endian - Neste esquema, o byte de ordem superior é armazenado no endereço inicial (A) e o byte de ordem inferior é armazenado no próximo endereço (A + 1).

Para permitir que máquinas com diferentes convenções de ordem de bytes se comuniquem entre si, os protocolos da Internet especificam uma convenção de ordem de bytes canônica para dados transmitidos pela rede. Isso é conhecido como Network Byte Order.

Ao estabelecer uma conexão de soquete da Internet, você deve se certificar de que os dados nos membros sin_port e sin_addr da estrutura sockaddr_in estão representados na Ordem de Bytes da Rede.

Funções de ordenação de bytes

As rotinas para conversão de dados entre a representação interna de um host e a Ordem de Byte da Rede são as seguintes -

Função Descrição
htons () Curto de host para rede
htonl () Host para rede longa
ntohl () Rede para hospedar longa
ntohs () Rede para hospedar curto

Listados abaixo estão mais alguns detalhes sobre essas funções -

  • unsigned short htons(unsigned short hostshort) - Esta função converte quantidades de 16 bits (2 bytes) da ordem de bytes do host para a ordem de bytes da rede.

  • unsigned long htonl(unsigned long hostlong) - Esta função converte quantidades de 32 bits (4 bytes) da ordem de bytes do host para a ordem de bytes da rede.

  • unsigned short ntohs(unsigned short netshort) - Esta função converte quantidades de 16 bits (2 bytes) da ordem de bytes da rede para a ordem de bytes do host.

  • unsigned long ntohl(unsigned long netlong) - Esta função converte quantidades de 32 bits da ordem de bytes da rede para a ordem de bytes do host.

Essas funções são macros e resultam na inserção do código-fonte de conversão no programa de chamada. Em máquinas little-endian, o código mudará os valores para a ordem de bytes da rede. Em máquinas big-endian, nenhum código é inserido, pois nenhum é necessário; as funções são definidas como nulas.

Programa para determinar a ordem de bytes do host

Mantenha o seguinte código em um arquivo byteorder.c , compile-o e execute-o em sua máquina.

Neste exemplo, armazenamos o valor de dois bytes 0x0102 no inteiro curto e, em seguida, olhamos para os dois bytes consecutivos, c [0] (o endereço A) ec [1] (o endereço A + 1) para determinar o byte ordem.

#include <stdio.h>

int main(int argc, char **argv) {

   union {
      short s;
      char c[sizeof(short)];
   }un;
	
   un.s = 0x0102;
   
   if (sizeof(short) == 2) {
      if (un.c[0] == 1 && un.c[1] == 2)
         printf("big-endian\n");
      
      else if (un.c[0] == 2 && un.c[1] == 1)
         printf("little-endian\n");
      
      else
         printf("unknown\n");
   }
   else {
      printf("sizeof(short) = %d\n", sizeof(short));
   }
	
   exit(0);
}

Uma saída gerada por este programa em uma máquina Pentium é a seguinte -

$> gcc byteorder.c
$> ./a.out
little-endian
$>