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

有两种顺序。一种是字节顺序,一种是位域顺序。C语言中的位域顺序没有标准的顺序。这取决于编译器。通常,位域的顺序在大端和小端之间颠倒。

于 2009-05-14T15:42:26.920 回答
11

这是依赖于编译器且不可移植的。位字段的排序方式取决于实现,这里最好使用 8 位字段和移位/掩码来获得子字段。

于 2009-05-14T15:43:41.690 回答
2

在这台机器中,字节序可能也指位顺序和字节顺序。这篇维基百科文章提到有时会出现这种情况。

于 2009-05-14T15:43:24.997 回答
1

我的理解是位顺序和字节顺序通常是两个不同的东西。具有位域的结构通常不能跨编译器/架构移植。有时 ifdef 可用于支持不同的位排序。在这种情况下,字节顺序实际上是无关紧要的,它应该是关于位排序的 ifdef。在某些情况下,某些字节顺序具有特定位顺序的假设可能是正确的。

于 2009-05-15T00:04:47.977 回答
0

我对评论的解读是,这两个单字节字段一起被解释为一个双字节值(或者曾经——似乎无论如何都没有使用一个字节)。它们不是声明一个两字节值,而是声明两个一字节值,但根据字节序颠倒声明顺序。

于 2009-05-14T15:41:05.987 回答
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 回答