リトルエンディアン[LE]マシン[Linux、Intelプロセッサ]で次のプログラムを実行しました。以下のコードスニペットで3つの出力を説明することはできません。マシンはLEであるため、a
の値は_0x78563412
_として格納されます。印刷時には、実際の値を表示しています。 LEマシンなので、ntohl()
はノーオペレーションであり、_0x78563412
_を表示することを期待しています。ただし、htonl()
を含む2番目の印刷ステートメントには_0x12345678
_が必要です。誰かが私が彼らが同じである理由を理解するのを手伝ってくれませんか?
_int main()
{
int a = 0x12345678;
printf("Original - 0x%x\n", (a));
printf("Network - 0x%x\n", htonl(a));
printf("Host - 0x%x\n", ntohl(a));
return 0;
}
_
出力:
_Original - 0x12345678
Network - 0x78563412
Host - 0x78563412
_
LEマシンなので、
ntohl()
は何もしないと思います
それは間違いです。ネットワークのバイト順序はビッグエンディアン、ホストのバイト順序はリトルエンディアンです。したがって、ntohl
とhtonl
はどちらも、入力のバイトスワップバージョンを返します。
htonl
のポイントは、ホストで整数を取り、次のように書くことができるということです。
_int i = htonl(a);
_
その結果、i
のメモリネットワークバイトオーダーを使用して解釈した場合は、a
と同じ値になります。したがって、i
のオブジェクト表現をソケットに書き込み、もう一方のエンドのリーダーがネットワークバイトオーダーの4バイト整数を期待する場合、a
の値を読み取ります。
_
0x78563412
_を表示します
これはあなたが書くつもりだったものですか? ntohl
がno-op(つまり、恒等関数)の場合、ntohl(a) == a
があるため、3行目は必ず1行目と同じものを出力します。これは、プログラムが出力するビッグエンディアンの実装で発生することです。
_Original - 0x12345678
Network - 0x12345678
Host - 0x12345678
_
htonl
とntohl
はまったく同じ関数です。それらはhtonl(ntohl(x)) == x
を満たすことになっています。それらは、ドキュメントのためだけに異なる名前が付けられています(同じであっても、ホストからネットワークへ、またはその逆に変換することを明示します)。したがって、リトルエンディアンのマシンでは、どちらもバイトスワッピングを実行し、ビッグエンディアンのマシンでは、どちらもノーオペレーションです。
a
を値で渡しているため、これらの関数のいずれによっても変更されません。
htonl()
とntohl()
がreturningであるものを出力しています。
編集して追加:私はあなたが1つがノーオペレーションだと思ったところを逃しました。そうではありません。どちらもLEマシンでまったく同じことをします。バイト順序を逆にします。 ntohl()
は、int
の順序でネットワークバイトを渡すことを期待しています。
プログラムで_int a;
_ yoと書くと、a
にホスト順の整数が含まれていることがわかりますが、プログラムはそれを認識していません。ネットワークの順序で値がすでに含まれているintを簡単に指定できます。もちろん、ホストの順序にない値に対して算術演算子を使用すると、ネットワークの順序がホストの順序と同じでない場合、ネットワークの観点からは結果が不正確になります。
しかし、これは今のところフェッチされていません。ネットワークで順序付けられた値は、送信前または受信直後に、低レベルの構造で正確にそのように保持されることがよくあります。
プログラムの何が問題なのかというと、ntohl()
を呼び出すと、提供しているint
がネットワークのメモリに格納されている値であるというntohl()
関数を約束しているということです。注文。それが契約です。それが真実でない場合、関数はあなたが期待することを実行しません、そしてそれはあなたが狙っているものです。
他のほとんどのシステムで説明されているように(大きなまたは小さなが愚かなエンディアンではない)、2つの関数は通常同じであり、バイトが逆になるか、操作がありません。