Я скомпилировал пример, и пример не распечатывает локальный IP-адрес аппарата.
GetAdaptersAddresses()
всегда работал нормально для меня.
где находится IP-адрес в структуре IP_ADAPTER_ADDRESSES_LH?
В структуре потенциально может быть много IP-адресов, в зависимости от того, какой вид интересующего вас IP-адреса - Unicast, Anycast, Multicast или DnsServer. Для локально назначенных IP-адресов вы обычно используете только одноадресные адреса:
Поле IP_ADAPTER_ADDRESSES_LH::FirstUnicastAddress
указывает на связанный список структур IP_ADAPTER_UNICAST_ADDRESS_LH
, по одной записи для каждого IP-адреса. Используйте поле IP_ADAPTER_UNICAST_ADDRESS_LH::Next
для циклического перемещения по списку (пример MSDN показывает такой цикл, но он только подсчитывает количество элементов в списке, но не распечатывает содержимое списка).
Поле IP_ADAPTER_UNICAST_ADDRESS_LH::Address
содержит фактический IP-адрес в формате SOCKET_ADDRESS
.
поле SOCKET_ADDRESS::lpSockaddr
является указателем SOCKADDR*
. Вы можете передать его как есть API-интерфейсам сокетов, например bind()
.
Если вы хотите что-то сделать с IP-адресом (например, отобразить его), вы должны привести указатель SOCKET_ADDRESS::lpSockAddr
к sockaddr_in*
или sockaddr_in6*
, в зависимости от того, является ли IP-адрес IPv4 или IPv6, соответственно (используйте поле SOCKADDR::sa_family
, чтобы определить правильный тип - AF_INET
для sockaddr_in
, AF_INET6
для sockaddr_in6
). Затем вы можете получить доступ к полю sockaddr_in::sin_addr
или sockaddr_in6::sin6_addr
при необходимости, которое содержит фактические байты IP-адреса.
Например:
PIP_ADAPTER_ADDRESSES pAddresses = ...; // allocate buffer as needed...
ULONG ulSize = ...; // size of allocated buffer...
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, NULL, pAddresses, &ulSize) == 0)
{
for (PIP_ADAPTER_UNICAST_ADDRESS_LH *pAddress = pAddresses->FirstUnicastAddress;
pAddress != NULL;
pAddress = pAddress->Next)
{
SOCKADDR *pSockAddr = pAddress->Address.lpSockaddr;
switch (pSockAddr->sa_family)
{
case AF_INET: {
sockaddr_in *pInAddr = (sockaddr_in*) pSockAddr;
// use pInAddr->sin_addr as needed...
break;
}
case AF_INET6: {
sockaddr_in6 *pIn6Addr = (sockaddr_in6*) pSockAddr;
// use pIn6Addr->sin6_addr as needed...
break;
}
}
}
}
// free pAddresses as needed ...