バイトオーダー#
バイトオーダー:バイトの順序を格納する。
バイトオーダーは CPU のアーキテクチャに関連しており、通常 x86 アーキテクチャではリトルエンディアンが使用され、バイトオーダーはデータがメモリ内に格納される順序を決定します。
データのネットワーク通信時には、バイトオーダーを統一する必要があります。これにより、データの正常な転送と解析が保証されます。
データの格納方法には、ビッグエンディアン(Big-Endian)とリトルエンディアン(Little-Endian)があります。
ビッグエンディアン:上位バイトが低いアドレスに格納され、下位バイトが高いアドレスに格納されます(低位から高位)。
リトルエンディアン:上位バイトが高いアドレスに格納され、下位バイトが低いアドレスに格納されます(低位から低位)。
0x1234
の 16 進数の場合、12
が上位バイトであり、34
が下位バイトです。また、高いアドレスと低いアドレスはアドレスの大きさを指します。例えば、アドレス0x1010
と0x1011
がある場合、0x1010
は低いアドレスであり、0x1011
は高いアドレスです。
ホストのバイトオーダーを判断する#
// 1バイト = 8ビット(8ビットの2進数が1バイトを表す)
// 1つの16進数は4ビットを表す
// shortは2バイト = 16ビットを占有する
// charにキャストし、取得した最初のアドレス(低いアドレス)は1バイトを占有する
// この低いアドレスをデリファレンスしてshortに変換する
// 元のデータの下位と上位と比較する
// 上位と等しい場合、ビッグエンディアン(低位から高位)であることを示す
// 下位と等しい場合、リトルエンディアン(低位から低位)であることを示す
// ビッグエンディアンの場合、低いアドレスにデータの上位バイトが格納される
// 上位バイトは0x12
// &iは低いアドレスを取得する
// (short)*(char *)&i == 0x12
bool isBigEndian() {
short i = 0x1234;
return (short)*(char *)&i == 0x12;
}
// リトルエンディアンの場合、低いアドレスにデータの下位バイトが格納される
// 下位バイトは0x34
// &iは低いアドレスを取得する
// (short)*(char *)&i == 0x34
bool isLittleEndian() {
short i = 0x1234;
return (short)*(char *)&i == 0x34;
}
簡単な方法:
bool isBigEndian() {
short i = 1;
return *(char *)&i != 1;
}
ホストのバイトオーダーとネットワークのバイトオーダーの変換#
ネットワークのバイトオーダーは通常ビッグエンディアンを使用します。
POSIX API#
// ホストからネットワークへの符号なしショート
htons();
// ホストからネットワークへの符号なしロング
htonl();
// ネットワークからホストへの符号なしショート
ntohs();
// ネットワークからホストへの符号なしロング
ntohl();
Boost Asio API#
// ホストからネットワークへの符号なしショート
boost::asio::detail::socket_ops::host_to_network_short();
// ホストからネットワークへの符号なしロング
boost::asio::detail::socket_ops::host_to_network_long();
// ネットワークからホストへの符号なしショート
boost::asio::detail::socket_ops::network_to_host_short();
// ネットワークからホストへの符号なしロング
boost::asio::detail::socket_ops::network_to_host_long();
これらの API を使用する際には、入力パラメータと返される結果が符号なし整数であることを確認する必要があります。そうでない場合、符号の拡張の問題が発生する可能性があります。