Unix Socket - Ordini di byte di rete

Sfortunatamente, non tutti i computer memorizzano i byte che comprendono un valore multibyte nello stesso ordine. Considera una connessione Internet a 16 bit composta da 2 byte. Esistono due modi per memorizzare questo valore.

  • Little Endian - In questo schema, il byte di ordine inferiore viene memorizzato sull'indirizzo iniziale (A) e il byte di ordine superiore viene memorizzato sull'indirizzo successivo (A + 1).

  • Big Endian - In questo schema, il byte di ordine superiore viene memorizzato sull'indirizzo iniziale (A) e il byte di ordine inferiore viene memorizzato sull'indirizzo successivo (A + 1).

Per consentire a macchine con diverse convenzioni di ordine dei byte di comunicare tra loro, i protocolli Internet specificano una convenzione canonica di ordine dei byte per i dati trasmessi sulla rete. Questo è noto come Network Byte Order.

Quando si stabilisce una connessione socket Internet, è necessario assicurarsi che i dati nei membri sin_port e sin_addr della struttura sockaddr_in siano rappresentati in Network Byte Order.

Funzioni di ordinamento dei byte

Le routine per la conversione dei dati tra la rappresentazione interna di un host e Network Byte Order sono le seguenti:

Funzione Descrizione
htons () Host to Network Short
htonl () Host to Network Long
ntohl () Rete per ospitare a lungo
ntohs () Rete per ospitare breve

Di seguito sono elencati alcuni dettagli in più su queste funzioni:

  • unsigned short htons(unsigned short hostshort) - Questa funzione converte le quantità a 16 bit (2 byte) dall'ordine di byte dell'host all'ordine di byte di rete.

  • unsigned long htonl(unsigned long hostlong) - Questa funzione converte le quantità a 32 bit (4 byte) dall'ordine di byte dell'host all'ordine di byte di rete.

  • unsigned short ntohs(unsigned short netshort) - Questa funzione converte le quantità a 16 bit (2 byte) dall'ordine dei byte di rete all'ordine dei byte host.

  • unsigned long ntohl(unsigned long netlong) - Questa funzione converte le quantità a 32 bit dall'ordine dei byte di rete all'ordine dei byte host.

Queste funzioni sono macro e determinano l'inserimento del codice sorgente di conversione nel programma chiamante. Sulle macchine Little Endian, il codice cambierà i valori intorno all'ordine dei byte di rete. Sulle macchine big-endian, non viene inserito alcun codice poiché non è necessario; le funzioni sono definite come null.

Programma per determinare l'ordine dei byte host

Conserva il codice seguente in un file byteorder.c, quindi compilarlo ed eseguirlo sulla tua macchina.

In questo esempio, memorizziamo il valore a due byte 0x0102 nel numero intero corto e quindi guardiamo i due byte consecutivi, c [0] (l'indirizzo A) ec [1] (l'indirizzo A + 1) per determinare il byte ordine.

#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);
}

Un output generato da questo programma su una macchina Pentium è il seguente:

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