Socket Unix - Ordres d'octets réseau

Malheureusement, tous les ordinateurs ne stockent pas les octets qui composent une valeur multi-octets dans le même ordre. Considérez un Internet 16 bits composé de 2 octets. Il existe deux manières de stocker cette valeur.

  • Little Endian - Dans ce schéma, l'octet de poids faible est stocké sur l'adresse de départ (A) et l'octet de poids fort est stocké sur l'adresse suivante (A + 1).

  • Big Endian - Dans ce schéma, l'octet de poids fort est stocké sur l'adresse de départ (A) et l'octet de poids faible est stocké sur l'adresse suivante (A + 1).

Pour permettre aux machines avec différentes conventions d'ordre d'octet de communiquer entre elles, les protocoles Internet spécifient une convention d'ordre d'octet canonique pour les données transmises sur le réseau. C'est ce qu'on appelle l'ordre des octets du réseau.

Lors de l'établissement d'une connexion de socket Internet, vous devez vous assurer que les données des membres sin_port et sin_addr de la structure sockaddr_in sont représentées dans l'ordre des octets du réseau.

Fonctions de classement des octets

Les routines de conversion des données entre la représentation interne d'un hôte et l'ordre des octets du réseau sont les suivantes:

Fonction La description
htons () Host to Network Short
htonl () Hôte vers réseau long
ntohl () Réseau pour héberger longtemps
ntohs () Réseau à hôte court

Vous trouverez ci-dessous plus de détails sur ces fonctions -

  • unsigned short htons(unsigned short hostshort) - Cette fonction convertit les quantités 16 bits (2 octets) de l'ordre des octets de l'hôte en ordre des octets du réseau.

  • unsigned long htonl(unsigned long hostlong) - Cette fonction convertit les quantités 32 bits (4 octets) de l'ordre des octets de l'hôte en ordre des octets du réseau.

  • unsigned short ntohs(unsigned short netshort) - Cette fonction convertit les quantités 16 bits (2 octets) de l'ordre des octets du réseau en ordre des octets de l'hôte.

  • unsigned long ntohl(unsigned long netlong) - Cette fonction convertit les quantités 32 bits de l'ordre des octets du réseau en ordre des octets de l'hôte.

Ces fonctions sont des macros et entraînent l'insertion du code source de la conversion dans le programme appelant. Sur les machines little-endian, le code changera les valeurs autour de l'ordre des octets du réseau. Sur les machines big-endian, aucun code n'est inséré car aucun n'est nécessaire; les fonctions sont définies comme nulles.

Programme pour déterminer l'ordre des octets de l'hôte

Conservez le code suivant dans un fichier byteorder.c , puis compilez-le et exécutez-le sur votre ordinateur .

Dans cet exemple, nous stockons la valeur de deux octets 0x0102 dans l'entier court, puis regardons les deux octets consécutifs, c [0] (l'adresse A) et c [1] (l'adresse A + 1) pour déterminer l'octet ordre.

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

Une sortie générée par ce programme sur une machine Pentium est la suivante -

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