inet_ntop 返回部分不正确的 IPv6 地址

inet_ntop returning partically incorrect IPv6 address

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

在我的 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

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

The address_len parameter should be initialized to indicate the amount of space pointed to by address. On return it contains the actual size of the address returned (in bytes).

The address is truncated if the buffer provided is too small.

struct sockaddr 的大小对于 IPv6 地址而言太小,将导致地址被截断。

您需要将 struct sockaddr_storagegetpeername 一起使用,而不仅仅是 struct sockaddr

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