Gniazdo Unix - kolejność bajtów w sieci

Niestety nie wszystkie komputery przechowują bajty zawierające wartość wielobajtową w tej samej kolejności. Rozważmy 16-bitowy Internet, który składa się z 2 bajtów. Istnieją dwa sposoby przechowywania tej wartości.

  • Little Endian - W tym schemacie młodszy bajt jest przechowywany pod adresem początkowym (A), a najstarszy bajt jest przechowywany pod następnym adresem (A + 1).

  • Big Endian - W tym schemacie najstarszy bajt jest przechowywany pod adresem początkowym (A), a najmniejszy bajt jest przechowywany pod następnym adresem (A + 1).

Aby umożliwić komunikację między maszynami o różnych konwencjach kolejności bajtów, protokoły internetowe określają kanoniczną konwencję kolejności bajtów dla danych przesyłanych w sieci. Jest to znane jako kolejność bajtów w sieci.

Podczas ustanawiania połączenia internetowego przez gniazdo należy upewnić się, że dane w elementach sin_port i sin_addr struktury sockaddr_in są reprezentowane w sieciowej kolejności bajtów.

Funkcje porządkowania bajtów

Procedury konwersji danych między wewnętrzną reprezentacją hosta a kolejnością bajtów sieci są następujące -

Funkcjonować Opis
htons () Host do sieci Short
htonl () Host do sieci długo
ntohl () Sieć do hostowania długo
ntohs () Sieć do hostowania Short

Poniżej znajduje się więcej szczegółów na temat tych funkcji -

  • unsigned short htons(unsigned short hostshort) - Ta funkcja konwertuje wartości 16-bitowe (2-bajtowe) z kolejności bajtów hosta na kolejność bajtów sieci.

  • unsigned long htonl(unsigned long hostlong) - Ta funkcja konwertuje wielkości 32-bitowe (4-bajtowe) z kolejności bajtów hosta na kolejność bajtów sieci.

  • unsigned short ntohs(unsigned short netshort) - Ta funkcja konwertuje wartości 16-bitowe (2-bajtowe) z sieciowej kolejności bajtów na kolejność bajtów hosta.

  • unsigned long ntohl(unsigned long netlong) - Ta funkcja konwertuje ilości 32-bitowe z kolejności bajtów sieci na kolejność bajtów hosta.

Funkcje te są makrami i powodują wstawienie kodu źródłowego konwersji do programu wywołującego. Na maszynach little-endian kod zmieni wartości na sieciową kolejność bajtów. Na maszynach typu big-endian żaden kod nie jest wstawiany, ponieważ nie jest potrzebny; funkcje są zdefiniowane jako null.

Program do określania kolejności bajtów hosta

Zachowaj następujący kod w pliku byteorder.c, a następnie skompiluj go i uruchom na swoim komputerze.

W tym przykładzie przechowujemy dwubajtową wartość 0x0102 w krótkiej liczbie całkowitej, a następnie patrzymy na dwa kolejne bajty, c [0] (adres A) ic [1] (adres A + 1), aby określić bajt zamówienie.

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

Dane wyjściowe generowane przez ten program na komputerze z procesorem Pentium są następujące -

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