首页 > 解决方案 > inet_ntop 返回部分不正确的 IPv6 地址

问题描述

我知道这个类似的问题,但答案没有意义,可能是针对不同的问题。

在我的 iOS 应用程序中,我使用 CFSockets 连接到服务器并希望显示服务器的远程地址。使用 IPv4 时,它按预期工作,但 IPv6 会出现奇怪的结果,其中地址的网络前缀是正确的,但主机位完全不同。

int sock_fd = <...> // Assume I already have the fd
struct sockaddr addr;
socklen_t addr_len = sizeof(addr);
getpeername(sock_fd, &addr, &addr_len);
char addressString[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr, addressString, INET6_ADDRSTRLEN);

我所期望的是,2607:f2f8:a4c8::2但我得到的是一个具有正确网络前缀但每次主机位不同的地址,例如:

               vvvvvvvvvvvvvvvvvvvv Random?
2607:f2f8:a4c8:0:c400:13b0:f6c5:afa
^^^^^^^^^^^^^^ Correct

标签: cposix

解决方案


的手册页getpeername(2)提示了为什么会发生这种情况:

address_len 参数应该被初始化以指示地址指向的空间量。返回时,它包含返回地址的实际大小(以字节为单位)。

如果提供的缓冲区太小,地址将被截断。

的大小struct sockaddr对于 IPv6 地址来说太小,会导致地址被截断。

您需要使用struct sockaddr_storagewithgetpeername而不仅仅是struct sockaddr

struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
getpeername(socket, (struct sockaddr *)&addr, &addr_len)

推荐阅读