IPv4 IPv6 Socket 编程相关结构


Structures for handling internet addresses

Prototypes

  1. include <netinet/in.h>  
  2.   
  3. // All pointers to socket address structures are often cast to pointers   
  4. // to this type before use in various functions and system calls:   
  5.   
  6. struct sockaddr {  
  7.     unsigned short    sa_family;    // address family, AF_xxx   
  8.     char              sa_data[14];  // 14 bytes of protocol address   
  9. };  
  10.   
  11.   
  12. // IPv4 AF_INET sockets:   
  13.   
  14. struct sockaddr_in {  
  15.     short            sin_family;   // e.g. AF_INET, AF_INET6   
  16.     unsigned short   sin_port;     // e.g. htons(3490)   
  17.     struct in_addr   sin_addr;     // see struct in_addr, below   
  18.     char             sin_zero[8];  // zero this if you want to   
  19. };  
  20.   
  21. struct in_addr {  
  22.     unsigned long s_addr;          // load with inet_pton()   
  23. };  
  24.   
  25.   
  26. // IPv6 AF_INET6 sockets:   
  27.   
  28. struct sockaddr_in6 {  
  29.     u_int16_t       sin6_family;   // address family, AF_INET6   
  30.     u_int16_t       sin6_port;     // port number, Network Byte Order   
  31.     u_int32_t       sin6_flowinfo; // IPv6 flow information   
  32.     struct in6_addr sin6_addr;     // IPv6 address   
  33.     u_int32_t       sin6_scope_id; // Scope ID   
  34. };  
  35.   
  36. struct in6_addr {  
  37.     unsigned char   s6_addr[16];   // load with inet_pton()   
  38. };  
  39.   
  40.   
  41. // General socket address holding structure, big enough to hold either   
  42. // struct sockaddr_in or struct sockaddr_in6 data:   
  43.   
  44. struct sockaddr_storage {  
  45.     sa_family_t  ss_family;     // address family   
  46.   
  47.     // all this is padding, implementation specific, ignore it:   
  48.     char      __ss_pad1[_SS_PAD1SIZE];  
  49.     int64_t   __ss_align;  
  50.     char      __ss_pad2[_SS_PAD2SIZE];  
  51. };  

Description

These are the basic structures for all syscalls and functions that deal with internet addresses. Often you'll usegetaddinfo() to fill these structures out, and then will read them when you have to.

In memory, the struct sockaddr_in and struct sockaddr_in6 share the same beginning structure asstruct sockaddr, and you can freely cast the pointer of one type to the other without any harm, except the possible end of the universe.

Just kidding on that end-of-the-universe thing...if the universe does end when you cast astruct sockaddr_in* to astruct sockaddr*, I promise you it's pure coincidence and you shouldn't even worry about it.

So, with that in mind, remember that whenever a function says it takes a struct sockaddr* you can cast your struct sockaddr_in*,struct sockaddr_in6*, orstruct sockadd_storage* to that type with ease and safety.

struct sockaddr_in is the structure used with IPv4 addresses (e.g. "192.0.2.10"). It holds an address family (AF_INET), a port insin_port, and an IPv4 address insin_addr.

There's also this sin_zero field in struct sockaddr_in which some people claim must be set to zero. Other people don't claim anything about it (the Linux documentation doesn't even mention it at all), and setting it to zero doesn't seem to be actually necessary. So, if you feel like it, set it to zero usingmemset().

Now, that struct in_addr is a weird beast on different systems. Sometimes it's a crazyunion with all kinds of#defines and other nonsense. But what you should do is only use thes_addr field in this structure, because many systems only implement that one.

struct sockadd_in6 and struct in6_addr are very similar, except they're used for IPv6.

struct sockaddr_storage is a struct you can pass toaccept() orrecvfrom() when you're trying to write IP version-agnostic code and you don't know if the new address is going to be IPv4 or IPv6. Thestruct sockaddr_storage structure is large enough to hold both types, unlike the original smallstruct sockaddr.

Example

  1. // IPv4:   
  2.   
  3. struct sockaddr_in ip4addr;  
  4. int s;  
  5.   
  6. ip4addr.sin_family = AF_INET;  
  7. ip4addr.sin_port = htons(3490);  
  8. inet_pton(AF_INET, "10.0.0.1", &ip4addr.sin_addr);  
  9.   
  10. s = socket(PF_INET, SOCK_STREAM, 0);  
  11. bind(s, (struct sockaddr*)&ip4addr, sizeof ip4addr);  
  12. // IPv6:   
  13.   
  14. struct sockaddr_in6 ip6addr;  
  15. int s;  
  16.   
  17. ip6addr.sin6_family = AF_INET6;  
  18. ip6addr.sin6_port = htons(4950);  
  19. inet_pton(AF_INET6, "2001:db8:8714:3a90::12", &ip6addr.sin6_addr);  
  20.   
  21. s = socket(PF_INET6, SOCK_STREAM, 0);  
  22. bind(s, (struct sockaddr*)&ip6addr, sizeof ip6addr);  
  23.    
  24.    
  25.    
  26. struct sockaddr_in, struct in_addrStructures for handling internet addressesPrototypes #include <netinet/in.h>  
  27.   
  28. struct sockaddr_in {  
  29.     short            sin_family;   // e.g. AF_INET   
  30.     unsigned short   sin_port;     // e.g. htons(3490)   
  31.     struct in_addr   sin_addr;     // see struct in_addr, below   
  32.     char             sin_zero[8];  // zero this if you want to   
  33. };  
  34.   
  35. struct in_addr {  
  36.     unsigned long s_addr;  // load with inet_aton()   
  37. };  
  38.  

Description

These are the basic structures for all syscalls and functions that deal with internet addresses. In memory, the struct sockaddr_in is the same size as struct sockaddr, and you can freely cast the pointer of one type to the other without any harm, except the possible end of the universe.

Just kidding on that end-of-the-universe thing...if the universe does end when you cast a struct sockaddr_in* to a struct sockaddr*, I promise you it's pure coincidence and you shouldn't even worry about it.

So, with that in mind, remember that whenever a function says it takes a struct sockaddr* you can cast your struct sockaddr_in* to that type with ease and safety.

There's also this sin_zero field which some people claim must be set to zero. Other people don't claim anything about it (the Linux documentation doesn't even mention it at all), and setting it to zero doesn't seem to be actually necessary. So, if you feel like it, set it to zero using memset().

Now, that struct in_addr is a weird beast on different systems. Sometimes it's a crazy union with all kinds of #defines and other nonsense. But what you should do is only use the s_addr field in this structure, because many systems only implement that one.

With IPv4 (what basically everyone in 2005 still uses), the struct s_addr is a 4-byte number that represents one digit in an IP address per byte. (You won't ever see an IP address with a number in it greater than 255.)

-->
Example

struct sockaddr_in myaddr; int s; myaddr.sin_family = AF_INET; myaddr.sin_port = htons(3490); inet_aton("63.161.169.137", &myaddr.sin_addr.s_addr); s = socket(PF_INET, SOCK_STREAM, 0); bind(s, (struct sockaddr*)myaddr, sizeof(myaddr));

相关内容