是不是struct sockadr_in应该适用于IPv4和IPv6?

具体而言,sin_addr似乎位于IPv4和IPv6套接字的不同内存位置。 这会导致怪异:

#include <stdio.h> #include <netinet/in.h> int main(int argc, char ** argv) { struct sockaddr_in sa; printf("sin_addr in sockaddr_in = %p\n", &sa.sin_addr); printf("sin_addr in sockaddr_in6 = %p\n", &((struct sockaddr_in6*)&sa)->sin6_addr); }; 

输出:

 sin_addr in sockaddr_in = 0x7fffa26102b4 sin_addr in sockaddr_in6 = 0x7fffa26102b8 

为什么这两个值不一样?

由于这是指向相同的数据(要连接的地址),这应该位于相同的地址。 否则,你应该如何用sockaddr_in调用inet_ntop,你不知道是IPv4还是IPv6?

Solutions Collecting From Web of "是不是struct sockadr_in应该适用于IPv4和IPv6?"

为什么这两个值不一样?

sockaddr_insockaddr_in6是用于不同地址系列(分别为IPv4和IPv6)的不同结构。 除了一个以外,它们不需要互相兼容 – 第一个字段必须是16位整数来保存地址族。 sockaddr_in始终将该字段设置为AF_INET ,并且sockaddr_in6始终将该字段设置为AF_INET6 。 通过以这种方式标准化家族字段,任何基于sockaddr的API都可以访问该字段,并知道如何根据需要解释其余的结构数据。 这也是为什么基于sockaddr的API通常也具有int大小值作为输入/输出的原因,因为sockaddr_insockaddr_in6是不同的字节大小,所以API需要能够验证您传递的任何缓冲区的大小。

由于这是指向相同的数据(要连接的地址),这应该位于相同的地址。

不,不应该。 结构中的地址字段的位置是特定于该结构所属的地址族的类型的。 没有要求sockaddr_insockaddr_in6应该存储他们的地址在完全相同的偏移量。

否则,你应该如何用sockaddr_in调用inet_ntop,你不知道是IPv4还是IPv6?

sockaddr_in只能与IPv4一起使用,而其他任何东西都不能使用, sockaddr_in6只能与IPv6一起使用。 如果你有一个sockaddr_in那么你隐式知道你有一个IPv4地址,如果你有一个sockaddr_in6那么你隐式知道你有一个IPv6地址。 您必须将这些信息指定给inet_ntop()以便知道如何解释您传递给它的数据:

 struct sockaddr_in sa; inet_ntop(AF_INET, &(sa.sin_addr), ...); 

 struct sockaddr_in6 sa; inet_ntop(AF_INET6, &(sa.sin6_addr), ...); 

为了帮助您编写与系列不相关的代码,应尽可能直接使用sockaddr_storage而不是sockaddr_insockaddr_in6sockaddr_storage的大小足以容纳sockaddr_insockaddr_in6结构。 由于这两个结构体都以相同的偏移量和大小定义了一个族字段,所以sockaddr_storage可以与任何在sockaddr*指针( connect()accept()bind()getsockname()getpeername()等等上运行的API一起使用) 。

但是, inet_ntop()不属于该类别,所以在使用inet_ntop()inet_ntop()手动拆分sockaddr_storage ,例如:

 struct sockaddr_storage sa; switch (sa.ss_family) { case AF_INET: inet_ntop(AF_INET, &(((sockaddr_in*)&sa)->sin_addr), ...); break; case AF_INET6: inet_ntop(AF_INET6, &(((sockaddr_in6*)&sa)->sin6_addr), ...); break; } 

不,对于ipv6你需要使用

 in6_addr // is used to store the 128-bit network address 

 sockaddr_in6 

细节可以参考这里

为了编写支持双栈的代码,即使用ipv4和6