从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}}具有类似的布局?
答案 0 :(得分:2)
为了在C套接字API中提供一种穷人的多态性,C套接字函数只需要一个指向struct sockaddr *
的指针,它将接受可能有许多不同系列的地址。
这依赖于C中的保证,即结构的第一个成员的地址与结构的地址相同。由于每个sockaddr_*
类型的第一个成员都是地址系列,因此内部代码可以检查系列以回送到正确的地址结构。
因此,即使在转换为sockaddr *
并且相应地处理它之后,这也允许调用推断您已经传递了IPv6地址。
答案 1 :(得分:1)
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或另一个。