I know that sockaddr_in is for IPv4, and sockaddr_in6 for IPv6. The confusion to me is the difference between sockaddr and sockaddr_in[6].
Some functions accept sockaddr
and some functions accept sockaddr_in
or sockaddr_in6
, so:
- what's the rule?
- And why is there a need for two different structures?
And because the sizeof(sockaddr_in6) > sizeof(sockaddr) == sizeof(sockaddr_in)
.
- Does that mean we should always use sockaddr_in6 to allocate memory in stack and cast to sockaddr and sockaddr_in if we need to support ipv4 and ipv6?
One example is: we have a socket, and we want to get the string ip address of it (it can be ipv4 or ipv6).
We first call getsockname
to get an addr
and then call inet_ntop
based on the addr.sa_family
.
Is there anything wrong with this code snippet?
char ipStr[256];
sockaddr_in6 addr_inv6;
sockaddr* addr = (sockaddr*)&addr_inv6;
sockaddr_in* addr_in = (sockaddr_in*)&addr_inv6;
socklen_t len = sizeof(addr_inv6);
getsockname(_socket, addr, &len);
if (addr->sa_family == AF_INET6) {
inet_ntop(addr_inv6.sin6_family, &addr_inv6.sin6_addr, ipStr, sizeof(ipStr));
// <<<<<<<<IS THIS LINE VALID, getsockname expected a sockaddr, but we use
// it output parameter as sockaddr_in6.
} else {
inet_ntop(addr_in->sin_family, &addr_in->sin_addr, ipStr, sizeof(ipStr));
}
See Question&Answers more detail:os