Я знаю, что sockaddr_in для IPv4 и sockaddr_in6 для IPv6. Меня замешала разница между sockaddr и sockaddr_in [6].
Некоторые функции принимают sockaddr
, а некоторые функции принимают sockaddr_in
или sockaddr_in6
, поэтому:
- какое правило?
- И почему существует потребность в двух разных структурах?
И поскольку sizeof(sockaddr_in6) > sizeof(sockaddr) == sizeof(sockaddr_in)
.
- Означает ли это, что мы всегда должны использовать sockaddr_in6 для выделения памяти в стеке и приведения к sockaddr и sockaddr_in, если нам нужно поддерживать ipv4 и ipv6?
Один пример: у нас есть сокет, и мы хотим получить его IP-адрес (это может быть ipv4 или ipv6).
Сначала вызываем getsockname
для получения addr
, а затем вызываем inet_ntop
на основе addr.sa_family
.
Что-то не так с этим фрагментом кода?
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);
char ipStr[256];
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));
}