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:
And because the sizeof(sockaddr_in6) > sizeof(sockaddr) == sizeof(sockaddr_in)
.
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)); }
The SOCKADDR_IN structure specifies a transport address and port for the AF_INET address family.
The SOCKADDR_STORAGE structure stores socket address information. Since the SOCKADDR_STORAGE structure is sufficiently large to store address information for IPv4, IPv6, or other address families, its use promotes protocol-family and protocol-version independence and simplifies cross-platform development.
sockaddr_in
and sockaddr_in6
are both structures where first member is a sockaddr
structure.
According to the C standard, the address of a structure and its first member are the same, so you can cast the pointer to sockaddr_in(6)
in a pointer to sockaddr
.
Functions taking sockaddr_in(6)
as parameter may modify the sockaddr
part, and functions taking sockaddr
as parameter just care about that part.
It's a bit like inheritance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With