9

htonlntohlに関して。これらの2行のコードのいずれかがfalseと評価されるのはいつですか。

 htonl(x) == ntohl(x);

 htonl(ntohl(x)) == htonl(htonl(x));

つまり、これら2つの操作が同じマシンで同等でないのはいつですか。私が考えることができる唯一のシナリオは、整数を表すための2の補数で動作しないマシンです。

理由は主に歴史的なものですか、コーディングの明確さのためですか、それとも他の理由ですか?

同じマシン上でのネットワークバイトオーダーへの変換とネットワークバイトオーダーからの変換がどちらの方向でも同じコードではない最新のアーキテクチャまたは環境は今日存在しますか?

4

3 に答える 3

8

私は何年も前にUNIVAC1100シリーズメインフレーム用のTCP/IPスタックを作成しました。これは、1の補数演算を備えた36ビットのワードアドレス可能なコンピュータアーキテクチャでした。

このマシンが通信I/Oを実行すると、外界から到着した8ビットバイトが各9ビットクォーターワードの下位8ビットに入れられます。したがって、このシステムでは、ntohl()は各クォーターワードの8ビットをワードの下位32ビット(上位4ビットはゼロ)に圧縮して、算術演算を実行できるようにします。

同様に、htonl()はワードの下位32ビットを取得し、この操作を元に戻して、各8ビット量を各9ビットクォーターワードの下位8ビットに入れます。

したがって、元の質問に答えるために、このコンピュータアーキテクチャでのntohl()とhtonl()の操作は互いに非常に異なっていました。

例えば:

COMP*                                 . COMPRESS A WORD
          LSSL      A0,36             . CLEAR OUT A0
          LSSL      A1,1              . THROW AWAY TOP BIT
          LDSL      A0,8              . GET 8 GOOD ONE'S
          LSSL      A1,1              .
          LDSL      A0,8              .
          LSSL      A1,1              .
          LDSL      A0,8              .
          LSSL      A1,1              .
          LDSL      A0,8              .
          J         0,X9              .
.
DCOMP*                                . DECOMPRESS A WORD
          LSSL      A0,36             . CLEAR A0
          LSSL      A1,4              . THROW OUT NOISE
          LDSL      A0,8              . MOVE 8 GOOD BITS
          LSSL      A0,1              . ADD 1 NOISE BIT
          LDSL      A0,8              . MOVE 8 GOOD BITS
          LSSL      A0,1              . ADD 1 NOISE BIT
          LDSL      A0,8              . MOVE 8 GOOD BITS
          LSSL      A0,1              . ADD 1 NOISE BIT
          LDSL      A0,8              . MOVE 8 GOOD BITS
          J         0,X9              .

COMPはntohl()と同等であり、DCOMPはhtonl()と同等です。UNIVAC 1100アセンブリコードに精通していない人のために:-)LSSLは「左シングルシフト論理」であり、いくつかの位置でレジスターです。LDSLは、指定された数のレジスタのペアである「左ダブルシフト論理」です。したがって、LDSL A0,8は連結されたA0をシフトし、A1レジスタは左に8ビット、A1の上位8ビットをA0の下位8ビットにシフトします。

このコードは1981年にUNIVAC1108用に作成されました。数年後、1100/90があり、Cコンパイラが成長したときに、BSD NET / 2 TCP / IP実装の移植を開始し、ntohl()とhtonlを実装しました。 () 似たような方法で。悲しいことに、私はその仕事を完了しませんでした。

一部のインターネットRFCで「オクテット」という用語が使用されている理由がわからない場合は、その日の一部のコンピューター(PDP-10、Univacsなど)に8ビットではない「バイト」があったためです。「オクテット」は、特に8ビットバイトとして定義されました。

于 2016-07-30T14:36:45.957 に答える
7

Posix仕様の元のドラフトは見つかりませんでしたが、最近オンラインで見つかったものにヒントがあります。

ネットワークバイトオーダーは、実際の値を処理するのに便利でない場合があります。このため、値を通常の整数として格納する方が賢明です。これは「ホストバイトオーダー」として知られています。ホストバイト順:

The most significant bit might not be stored in the first byte in address order.

**Bits might not be allocated to bytes in any obvious order at all.**

uint8_tオブジェクトに格納されている8ビット値は、同じ表現であるため、ホストのバイト順序との間で変換する必要はありません。16ビットおよび32ビットの値は、htonl()、htons()、ntohl()、およびntohs()関数を使用して変換できます。

興味深いのは、次のステートメントが

POSIX標準では、8ビット文字と2の補数演算が明示的に必要です。

つまり、基本的に1の補数マシンの実装についての私の考えは除外されます。

しかし、「明白な順序はまったくない」という声明は、基本的に、posix委員会が少なくともposix/unixがビッグエンディアンまたはリトルエンディアン以外で実行される可能性を検討したことを示唆しています。そのため、htonlとntohlをdiffernet実装として宣言することを除外することはできません。

したがって、簡単な答えは、「htonlとntohlは同じ実装ですが、2つの異なる関数のインターフェースは、未知のものとの将来の互換性のためです」です。

于 2012-07-25T08:52:23.290 に答える
-2

すべてのマシンが同じエンディアンを持っているわけではなく、これらのメソッドがそれを処理します。「ネットワーク順序」はビッグエンディアンであるとされています。ビッグエンディアンアーキテクチャを実行しているマシンがあり、ntohlを実行している場合、出力は入力と同じになります(エンディアンはネットワークと同じであるため)。マシンがリトルエンディアンアーキテクチャの場合、ntohlはデータをビッグエンディアンからリトルエンディアンに変換します。htonlについても同じことが言えます(必要に応じてホストデータをネットワークバイトオーダーに変換します)。質問に答えるために、エンディアンが異なる2台のマシン間でデータを送信する場合、これら2つの操作は同等ではありません。

于 2012-07-23T17:52:46.693 に答える