为什么IPv6地址需要sin6_family?

时间:2014-11-05 20:01:02

标签: c unix

man 7 ipv6,我们可以看到IPv6地址在内部表示如下:

struct sockaddr_in6 {
       sa_family_t     sin6_family;   /* AF_INET6 */
       in_port_t       sin6_port;     /* port number */
       uint32_t        sin6_flowinfo; /* IPv6 flow information */
       struct in6_addr sin6_addr;     /* IPv6 address */
       uint32_t        sin6_scope_id; /* Scope ID (new in 2.4) */
};

还有:

  

sin6_family始终设置为AF_INET6

如果sin6_family始终相同,为什么需要struct?这是否意味着将IPv4转换为IPv6更容易,因为{{1}}具有类似的布局?

2 个答案:

答案 0 :(得分:2)

为了在C套接字API中提供一种穷人的多态性,C套接字函数只需要一个指向struct sockaddr *的指针,它将接受可能有许多不同系列的地址。

这依赖于C中的保证,即结构的第一个成员的地址与结构的地址相同。由于每个sockaddr_*类型的第一个成员都是地址系列,因此内部代码可以检查系列以回送到正确的地址结构。

因此,即使在转换为sockaddr *并且相应地处理它之后,这也允许调用推断您已经传递了IPv6地址。

答案 1 :(得分:1)

来自the bind man-page

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
     

[...]
  为addr参数传递的实际结构将取决于地址族   sockaddr结构定义为:

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

此结构的唯一目的是强制转换addr中传递的结构指针,以避免编译器警告。
  [...]

所以你看,sa_family是隐式可扩展tagged-union的标记,将结构标记为专用的IPv6版本,而不是通用的未知,IPv4或另一个。