从GetAdaptersAddresses()获取IP_ADDRESS_STRING?

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; 

似乎build议人类可读IP地址string的唯一字段是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地址的旧的虚线string样式,因为它使用GetAdaptersInfo()更容易, 。

我的问题是:是否有一个真正的 IP Helper函数,可以将IP_ADAPTER_UNICAST_ADDRESS转换为IPv4虚线string(或IPv6string)?

Solutions Collecting From Web of "从GetAdaptersAddresses()获取IP_ADDRESS_STRING?"

您可以使用GetIpAddrTable – 返回的数据结构包含一个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, 0, 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", i, inet_ntoa(IPAddr) ); 

SOCKET_ADDRESSAddress包含一个SOCKET_ADDRESS ,其中包含LPSOCKADDR中的LPSOCKADDR – 可以使用WSAAddressToString将其转换为ipv4字符串形式。

看看SOCKADDR的文档。 这使我们得到了SOCKADDR_STORAGE的文档,它是IPv4和IPv6的辅助结构。

从sockaddr文档引用:

使用sockaddr的Winsock函数并不严格解释为指向sockaddr结构的指针。 在不同的地址族中,结构的解释是不同的。

对于ipv4,你可以将一个sockaddr指针转换成一个sockaddr_in指针,然后从那里访问IPv4地址信息。 然后,您可以使用您最喜欢的字符串生成器来生成一个点四格式的字符串。

 sockaddr_in* address = (sockaddr_in*) temp->Address.lpSockaddr; uint32_t ipv4 = address->sin_addr.S_un.S_addr; // First octet: address->sin_addr.S_un.S_un_b.s_b1 // Second octet: address->sin_addr.S_un.S_un_b.s_b2 // Third octet: address->sin_addr.S_un.S_un_b.s_b3 // Fourth octet: address->sin_addr.S_un.S_un_b.s_b4 

我可以想象,你也可以使用类似的方式为结构定义(在下面复制)施放ipv6的地址。

 struct sockaddr { ushort sa_family; char sa_data[14]; }; struct sockaddr_in { short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; struct sockaddr_in6 { short sin6_family; u_short sin6_port; u_long sin6_flowinfo; struct in6_addr sin6_addr; u_long sin6_scope_id; };