15

/netinet/tcp.h の TCP ヘッダーの定義を参照してください。

struct tcphdr
  {
    u_int16_t th_sport;         /* source port */
    u_int16_t th_dport;         /* destination port */
    tcp_seq th_seq;             /* sequence number */
    tcp_seq th_ack;             /* acknowledgement number */
#  if __BYTE_ORDER == __LITTLE_ENDIAN
    u_int8_t th_x2:4;           /* (unused) */
    u_int8_t th_off:4;          /* data offset */
#  endif
#  if __BYTE_ORDER == __BIG_ENDIAN
    u_int8_t th_off:4;          /* data offset */
    u_int8_t th_x2:4;           /* (unused) */
#  endif
    u_int8_t th_flags;
#  define TH_FIN        0x01
#  define TH_SYN        0x02
#  define TH_RST        0x04
#  define TH_PUSH       0x08
#  define TH_ACK        0x10
#  define TH_URG        0x20
    u_int16_t th_win;           /* window */
    u_int16_t th_sum;           /* checksum */
    u_int16_t th_urp;           /* urgent pointer */
};

8 ビット フィールドのエンディアンの順序が異なるのはなぜですか? 16 ビットと 32 ビットのフィールドのみがバイト オーダーに関係し、それぞれ ntohs と ntohl を使用してエンディアン間で変換できると思いました。8ビットのものを処理するための関数は何ですか? 何もない場合、リトル エンディアン マシンでこのヘッダーを使用する TCP は、ビッグ エンディアン マシンの TCP では機能しないようです。

4

6 に答える 6

21

順序は2種類あります。1つはバイトオーダー、もう1つはビットフィールドオーダーです。C言語のビットフィールドの順序に関する標準的な順序はありません。コンパイラによって異なります。通常、ビットフィールドの順序はビッグエンディアンとリトルエンディアンの間で逆になります。

于 2009-05-14T15:42:26.920 に答える
11

これはコンパイラに依存し、移植性はありません。ビットフィールドの順序は実装によって異なります。ここでは、8ビットフィールドとシフト/マスクを使用してサブフィールドを取得する方がはるかに優れています。

于 2009-05-14T15:43:41.690 に答える
2

このマシンでは、エンディアンがバイト順序だけでなくビット順序も参照している可能性があります。このウィキペディアの記事は、これが時々当てはまると述べています。

于 2009-05-14T15:43:24.997 に答える
1

私の理解では、ビットの順序とエンディアンは一般に2つの異なるものです。ビットフィールドを持つ構造体は、通常、コンパイラ/アーキテクチャ間で移植できません。ifdefを使用して、さまざまなビット順序をサポートできる場合があります。この場合、エンディアンは実際には無関係であり、ビットの順序についてはifdefである必要があります。一部のエンディアネスが特定のビット順序を持っているという仮定は、場合によっては当てはまる可能性があります。

于 2009-05-15T00:04:47.977 に答える
0

これは、「# ifdef __FAVOR_BSD」の場合にのみ実行されるコードであることを知っておくと役立つ場合があります。/usr/include/netinet/tcp.h からです

# ifdef __FAVOR_BSD
typedef u_int32_t tcp_seq;
/*
 * TCP header.
 * Per RFC 793, September, 1981.
 */
struct tcphdr
于 2011-02-27T23:51:22.567 に答える
0

コメントを読んだところ、2 つの 1 バイト フィールドが一緒になって 2 バイト値として解釈されます (または、とにかく 1 バイトが未使用のように見えます)。1 つの 2 バイト値を宣言するのではなく、2 つの 1 バイト値を宣言しますが、エンディアンに応じて宣言の順序を逆にします。

于 2009-05-14T15:41:05.987 に答える