我知道这个similar question,但是答案没有意义,可能是针对其他问题。
在我的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)
的手册页提供了有关发生这种情况的提示:
address_len参数应初始化以指示地址指向的空间量。返回时,它包含返回地址的实际大小(以字节为单位)。
如果提供的缓冲区太小,地址将被截断。
struct sockaddr
的大小对于IPv6地址而言太小,将导致该地址被截断。
您需要将struct sockaddr_storage
与getpeername
一起使用,而不仅仅是struct sockaddr
struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
getpeername(socket, (struct sockaddr *)&addr, &addr_len)