GetAdaptersAddresses()将以IP_ADAPTER_UNICAST_ADDRESS格式获取地址,其格式定义为:
typedef struct _IP_ADAPTER_UNICAST_ADDRESS { union { struct { ULONG Length; DWORD Flags; } ; } ; struct _IP_ADAPTER_UNICAST_ADDRESS *Next; SOCKET_ADDRESS Address; IP_PREFIX_ORIGIN PrefixOrigin; IP_SUFFIX_ORIGIN SuffixOrigin; IP_DAD_STATE DadState; ULONG ValidLifetime; ULONG PreferredLifetime; ULONG LeaseLifetime; UINT8 OnLinkPrefixLength; } IP_ADAPTER_UNICAST_ADDRESS,*PIP_ADAPTER_UNICAST_ADDRESS;
似乎建议人类可读的IP地址字符串的唯一字段是Address,它是一个SOCKET_ADDRESS结构,定义如下:
typedef struct _SOCKET_ADDRESS { LPSOCKADDR lpSockaddr; INT iSockaddrLength; } SOCKET_ADDRESS,*PSOCKET_ADDRESS;
反过来,它使用另一种结构SOCKADDR,定义为:
对不起,这是复杂的方式发布在这里,因为它取决于IPv4与IPv6和Windows版本…所以这里是定义的链接:
http://msdn.microsoft.com/en-us/library/ms740496%28v=VS.85%29.aspx
如果你还没有像我那样头晕目眩并且遵循这个定义的迷宫,你可能会注意到检索IP地址的旧的虚线字符串样式是一场噩梦,因为过去使用GetAdaptersInfo()要容易得多.
我的问题是:是否有真正的IP Helper功能可以将IP_ADAPTER_UNICAST_ADDRESS转换为IPv4点分支(或IPv6字符串)?
解决方法
您可以使用
GetIpAddrTable –
returned data structure包含一个DWORD dwAddr,它是IPv4地址.第一个链接上的示例代码应该显示您想要的内容.摘要向您展示我的意思:
if ( (dwRetVal = GetIpAddrTable( pIPAddrTable,&dwSize,0 )) != NO_ERROR ) { printf("GetIpAddrTable Failed with error %d\n",dwRetVal); if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,dwRetVal,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),// Default language (LPTSTR) & lpMsgBuf,NULL)) { printf("\tError: %s",lpMsgBuf); LocalFree(lpMsgBuf); } exit(1); } printf("\tNum Entries: %ld\n",pIPAddrTable->dwNumEntries); for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) { printf("\n\tInterface Index[%d]:\t%ld\n",i,pIPAddrTable->table[i].dwIndex); IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr; printf("\tIP Address[%d]: \t%s\n",inet_ntoa(IPAddr) );
IP_ADAPTER_UNICAST_ADDRESS在地址中包含SOCKET_ADDRESS,后者又包含lpSockAddr中的LPSOCKADDR – 您可以使用WSAAddressToString将其转换为ipv4字符串形式.