2015-09-17 12 views
5
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 

Die tatsächliche Struktur, die für das Argument addr übergeben wird, hängt von der Adressfamilie ab. Die sockaddr Struktur ist definiert als so etwas wie:Was ist der Zweck des Feldes sa_data in einem Sockaddr?

struct sockaddr { 
    sa_family_t sa_family; 
    char  sa_data[14]; 
} 

Also für eine IPv4-Adresse (AF_INET), die tatsächliche Struktur, die weitergegeben wird, ist dies:

/* Source http://linux.die.net/man/7/ip */ 

struct sockaddr_in { 
    sa_family_t sin_family; /* address family: AF_INET */ 
    in_port_t  sin_port; /* port in network byte order */ 
    struct in_addr sin_addr; /* internet address */ 
}; 

/* Internet address. */ 
struct in_addr { 
    uint32_t  s_addr;  /* address in network byte order */ 
}; 

Hat der bind Code lesen Sie den sockaddr.sa_family Wert und abhängig von dem Wert, den es findet, wird es dann die Struktur in die entsprechende Struktur wie sockaddr_in?

Warum ist die sa_data auf 14 Zeichen gesetzt? Wenn ich das richtig verstehe, ist das Feld sa_data nur ein Feld, das genügend Speicherplatz für alle Adressfamilien bietet. Vermutlich erwarteten die ursprünglichen Designer, dass 14 Zeichen breit genug wären, um allen zukünftigen Typen zu entsprechen.

+0

https://en.wikipedia.org/wiki/Type_punning – user3386109

Antwort

5

Nach der glibc manual:

Die Länge 14 der sa_data ist im wesentlichen beliebig.

Und die FreeBSD developers handbook erwähnt die folgenden:

Bitte beachten Sie die Unbestimmtheit, mit der das sa_data Feld deklariert ist, nur als ein Array von 14 Bytes, mit dem Kommentar Hinting kann es mehr als 14 von ihnen.

Diese Vagheit ist ziemlich absichtlich. Sockets ist eine sehr leistungsfähige Schnittstelle. Während die meisten Leute vielleicht denken, dass es nichts mehr als die Internet-Schnittstelle ist - und die meisten Anwendungen verwenden es wahrscheinlich für die heutzutage-Sockets können für fast jede Art von Interprozess Kommunikation verwendet werden, von denen das Internet (oder genauer gesagt , IP) ist nur eins.

Ja, das sa_family Feld wird verwendet, um zu erkennen, wie die Struktur zu behandeln übergeben (die struct sockaddr* in einem Aufruf gegossen wird zu binden). Sie können mehr darüber lesen, wie es auch in einer FreeBSD developers handbook funktioniert.

Und tatsächlich gibt es "polymorphe" (Unter-) Arten von sockaddr, in denen sa_data mehr als 16 Bytes enthält, zum Beispiel:

struct sockaddr_un { 
    sa_family_t sun_family;    /* AF_UNIX */ 
    char  sun_path[108];   /* pathname */ 
}; 
3

Die sockaddr Struktur als getaggt Vereinigung verwendet wird. Durch Lesen des Feldes sa_family kann es in eine Struktur der richtigen Form umgewandelt werden.

Die 14 Bytes sind beliebig. Es ist groß genug, um IPv4-Adressen aufzunehmen, aber nicht groß genug, um IPv6-Adressen aufzunehmen. Es gibt auch eine sockaddr_storage Struktur, die groß genug für beide ist. Lesen der Microsoft-Dokumentation auf SOCKADDR_STORAGE, kommt es in 128 Bytes, so viel größer als für IPv6 benötigt. Einige Linux-Header überprüfen, scheint es auch dort mindestens so groß zu sein.

Als Referenz die IPv6-Struktur ist:

struct sockaddr_in6 { 
    u_int16_t  sin6_family; // address family, AF_INET6 
    u_int16_t  sin6_port;  // port number, Network Byte Order 
    u_int32_t  sin6_flowinfo; // IPv6 flow information 
    struct in6_addr sin6_addr;  // IPv6 address 
    u_int32_t  sin6_scope_id; // Scope ID 
}; 

struct in6_addr { 
    unsigned char s6_addr[16]; // IPv6 address 
}; 

Wie Sie sehen können, das 16-Byte-s6_addr Feld ist bereits größer als das 14-Byte sa_data Feld auf seine eigenen. Die Gesamtgröße nach dem Feld sa_family beträgt 26 Byte.

Verwandte Themen