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字符串形式.