2009-05-14 12 views
15

Siehe die Definition von TCP-Header in /netinet/tcp.h:Warum hat ein 8-Bit-Feld eine Endiannität?

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 */ 
}; 

Warum wird das 8-Bit-Feld eine andere Reihenfolge in endianness hat? Ich dachte, nur 16-Bit und 32-Bit-Felder zählten mit Byte-Reihenfolge, und Sie könnten zwischen Endian mit Ntohs bzw. Ntohl konvertieren. Was wäre die Funktion für den Umgang mit 8-Bit-Dingen? Wenn es keine gibt, scheint es, dass ein TCP, der diesen Header auf einem kleinen Endian-Rechner verwendet, nicht mit einem TCP auf einem Big-Endian-Rechner arbeiten würde.

+0

Seltsam, auf welchem ​​System fanden Sie diese Header-Datei? – fbonnet

+0

Debian Linux. Diese Version ist enthalten, wenn __USE_BSD #definiert ist. – Claudiu

Antwort

21

Es gibt zwei Arten der Bestellung. Eine ist die Byte-Reihenfolge, eine ist die Bitfeld-Reihenfolge. Es gibt keine Standardreihenfolge für die Bitfeldreihenfolge in C-Sprache. Es hängt vom Compiler ab. Typischerweise ist die Reihenfolge der Bitfelder zwischen Big und Little Endian umgekehrt.

+1

das scheint die richtige Antwort zu sein, und ich habe eine vage Erinnerung daran, es vorher zu hören, aber ich kann nicht guten Gewissens ohne eine Erwähnung upvote ... können Sie eine bieten? – rmeador

+0

das ist die einzige Antwort, die für mich sinnvoll ist – Claudiu

+0

sollte das nicht __BIG_ENDIAN_BITFIELD/__ LITTLE_ENDIAN_BITFIELD dann sein? Oder nehmen sie implizit an, dass die Endianz zwischen Byte- und Bitfeld-Befehlen gleich bleibt? – Slava

0

Meine Lesung des Kommentars ist, dass die zwei Ein-Byte-Felder zusammen als ein Zwei-Byte-Wert ausgelegt sind (oder waren - scheint wie ein Byte ist sowieso nicht verwendet). Anstatt einen Zwei-Byte-Wert zu deklarieren, deklarieren sie zwei Ein-Byte-Werte, kehren aber die Deklarationsreihenfolge in Abhängigkeit von der Endian-Eigenschaft um.

+0

Nein, es ist klar beabsichtigt, zwei 4-Bit-Felder zu definieren. Siehe z.B. http://www.freesoft.org/CIE/Course/Section4/8.htm für das TCP-Header-Layout. –

3

Es ist möglich, dass in dieser Maschine die Endianess auch auf die Bit-Reihenfolge sowie die Byte-Reihenfolge bezieht. This wikipedia article erwähnt, dass dies manchmal der Fall ist.

+0

In dieser Frage hat es keine Beziehung zur Bit-Reihenfolge. – kcwu

11

Dies ist compilerabhängig und nicht portabel. Wie Bitfelder geordnet sind, hängt von der Implementierung ab, es wäre hier viel besser, ein 8-Bit-Feld und eine Verschiebung/Maske zu verwenden, um die Unterfelder zu erhalten.

+0

Klingt nach einem besseren Plan für mich. –

1

Mein Verständnis ist, dass Bit-Reihenfolge und Endianess in der Regel zwei verschiedene Dinge sind. Strukturen mit Bitfeldern sind im Allgemeinen über Compiler/Architekturen nicht portierbar. Manchmal können ifdefs verwendet werden, um verschiedene Bit-Anordnungen zu unterstützen. In diesem Fall ist die Endianness wirklich irrelevant und es sollte ein Ifdef über die Bit-Reihenfolge sein. Die Annahme, dass einige Endianitäten eine bestimmte Bit-Reihenfolge haben, mag in einigen Fällen wahr sein.

0

Es kann helfen, zu wissen, dass dieser Code nur ausgeführt wird, wenn "# ifdef __ FAVOR_BSD". Es ist von /usr/include/netinet/tcp.h

# ifdef __FAVOR_BSD 
typedef u_int32_t tcp_seq; 
/* 
* TCP header. 
* Per RFC 793, September, 1981. 
*/ 
struct tcphdr