バイトオーダー
ネットワークと私
ネットワークアプリケーションの建築を考えた時、全ての開発者がぶつかる問題があります
それは、ネットワーク上にはどのようなコンピュータが存在するかわからないということです
しかし、サーバーは相手が誰であれ正しい結果を出さなければなりません
人種差別が悪であるように、機種差別もネットワークの世界では悪なのです
そこで、最初に問題となったのがネットワークバイトオーダーです
ワード単位の情報をビッグエンディアンとするかリトルエンディアンとするか
ネットワーク上の標準はどちらであるかという問題です
現代、多くのパーソナルコンピュータ市場は Intel とその互換プロセッサに支配され
その性質は、下位バイトから順にメモリに配置するリトルエンディアン形式です
アセンブリ経験者は理解していると思いますが、Intel の x86 プロセッサは
0xABCD というワード長のデータを 0xCDAB という順でメモリに保存しているのです
しかし、ネットワークの世界ではビッグエンディアンが標準なのです
これは、インターネットが建築された当時のコンピュータの性質が引き継がれているためです
WinSock では、この問題を解決する4つの関数が用意されています
これらを利用すれば、この問題を抽象化してワード長のデータを扱うことができます
ネットワークバイトオーダーへの変換は htons() と htonl() を
その逆は ntohs() と ntohl() 関数を使います
htons は host to network short の省略というような命名規則になっています
u_long htonl (u_long hostlong);
u_short htons (u_short hostshort);
u_long ntohl (u_long netlong);
u_short ntohs (u_short netshort);
htonl() と htons ()はホストバイトオーダーをネットワークバイトオーダーに変換します
hostlong には 32 ビットホストバイトオーダーを
hostshort には 16 ビットホストバイトオーダーを指定します
関数は、ネットワークバイトオーダー表現に変換して値を返します
ntohl() と ntohs() はネットワークバイトオーダーをホストバイトオーダーに変換します
netlong は 32 ビットネットワークバイトオーダーを
netshort には、16 ビットネットワークバイトオーダーを指定します
関数は、ホストバイトオーダー表現に値を変換して返します
#include <stdio.h>
#include <winsock2.h>
int main() {
unsigned int iValue = 0xAABBCCDD;
unsigned char *pc = (char *)&iValue;
printf("%X : %X : %X : %X\n" , pc[0] , pc[1] , pc[2] , pc[3]);
iValue = htonl(iValue);
printf("%X : %X : %X : %X\n" , pc[0] , pc[1] , pc[2] , pc[3]);
return 0;
}
このプログラムを実行すると、バイトオーダーの関係が目に見えて分かります
これは、x86 プロセッサのコンピュータならば、次のような結果を表示するでしょう
DD : CC : BB : AA
AA : BB : CC : DD
プログラムの最初に iValue 変数を 0xAABBCCDD で初期化していますが
リトルエンディアンコンピュータでは、下位から順にメモリに配置されます
バイトレベルで若い順にメモリを参照すると、それがよくわかります
次に、htonl() 関数を使って値をネットワークバイトオーダーに変換しています
2回目の printf() 関数の結果、ダブルワードの上位バイトから保存されていることがわかり
関数が、正しく情報をビッグエンディアン形式で保存していることが確認できます
ビッグエンディアンのシステム上で実行した場合 htonl() は何も行いません
htonl()
- u_long htonl (u_long hostlong);
- 32 ビットホストバイトオーダーをネットワークバイトオーダーに変換します
- hostlong
- 変換する 32 ビットホストバイトオーダーを指定します
- 戻り値
- 指定した値のネットワークバイトオーダー
htons()
- u_short htons (u_short hostshort);
- 16 ビットホストバイトオーダーをネットワークバイトオーダーに変換します
- hostlong
- 変換する 16 ビットホストバイトオーダーを指定します
- 戻り値
- 指定した値のネットワークバイトオーダー
ntohl()
- u_long ntohl (u_long netlong);
- 32 ビットネットワークバイトオーダーをホストバイトオーダーに変換します
- hostlong
- 変換する 32 ビットネットワークバイトオーダーを指定します
- 戻り値
- 指定した値のホストバイトオーダー
ntohs()
- u_short ntohs (u_short netshort);
- 16 ビットネットワークバイトオーダーをホストバイトオーダーに変換します
- hostlong
- 変換する 16 ビットネットワークバイトオーダーを指定します
- 戻り値
- 指定した値のホストバイトオーダー