Unixソケット-ネットワークバイトオーダー

残念ながら、すべてのコンピュータがマルチバイト値を構成するバイトを同じ順序で格納しているわけではありません。2バイトで構成される16ビットインターネットについて考えてみます。この値を保存する方法は2つあります。

  • Little Endian −この方式では、下位バイトは開始アドレス(A)に格納され、上位バイトは次のアドレス(A + 1)に格納されます。

  • Big Endian −この方式では、上位バイトは開始アドレス(A)に格納され、下位バイトは次のアドレス(A + 1)に格納されます。

異なるバイト順序規則を持つマシンが相互に通信できるようにするために、インターネットプロトコルは、ネットワークを介して送信されるデータの正規のバイト順序規則を指定します。これは、ネットワークバイトオーダーとして知られています。

インターネットソケット接続を確立するときは、sockaddr_in構造体のsin_portおよびsin_addrメンバーのデータがネットワークバイトオーダーで表されていることを確認する必要があります。

バイト順序関数

ホストの内部表現とネットワークバイトオーダーの間でデータを変換するためのルーチンは次のとおりです。

関数 説明
htons() ホストからネットワークへのショート
htonl() 長いネットワークへのホスト
ntohl() 長くホストするネットワーク
ntohs() ショートをホストするネットワーク

以下にリストされているのは、これらの関数の詳細です。

  • unsigned short htons(unsigned short hostshort) −この関数は、16ビット(2バイト)の量をホストバイトオーダーからネットワークバイトオーダーに変換します。

  • unsigned long htonl(unsigned long hostlong) −この関数は、32ビット(4バイト)の量をホストバイトオーダーからネットワークバイトオーダーに変換します。

  • unsigned short ntohs(unsigned short netshort) −この関数は、16ビット(2バイト)の量をネットワークバイトオーダーからホストバイトオーダーに変換します。

  • unsigned long ntohl(unsigned long netlong) −この関数は、32ビット量をネットワークバイトオーダーからホストバイトオーダーに変換します。

これらの関数はマクロであり、呼び出し側プログラムに変換ソースコードが挿入されます。リトルエンディアンのマシンでは、コードは値をネットワークバイトオーダーに変更します。ビッグエンディアンマシンでは、コードは必要ないため、コードは挿入されません。関数はnullとして定義されています。

ホストのバイト順序を決定するプログラム

次のコードをbyteorder.cファイルに保存し、コンパイルしてマシン上で実行します。

この例では、2バイト値0x0102を短整数で格納し、2つの連続するバイトc [0](アドレスA)とc [1](アドレスA + 1)を調べてバイトを決定します。注文。

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

このプログラムによってPentiumマシンで生成される出力は次のとおりです。

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