我正在使用 USB Internet 加密狗为我的计算机分配 IPv6 地址。当我使用ipconfig
时,我可以看到分配的IPv6地址,它是一个公共(public)IP。
当我使用GetAdaptersAddresses()
时,我得到了一个长链表,其中包含任播、多播和单播地址,但它们都与系统的 IP 地址不匹配。
还有其他地方可以获取系统的IP吗?我实际上想获取系统的 IP 地址,以便将其绑定(bind)到套接字。
我使用 Windows 7。
// getadaptersinfo.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include<WinSock2.h>
#include<iphlpapi.h>
#include<ws2tcpip.h>
#include<iostream>
#pragma comment(lib,"IPHLPAPI.lib")
#pragma comment(lib,"Ws2_32.lib")
using namespace std;
int main()
{
cout << "\nusing getadapteraddress";
PIP_ADAPTER_ADDRESSES p, tp;
ULONG u;
DWORD ret;
p = (IP_ADAPTER_ADDRESSES*)HeapAlloc(GetProcessHeap(), 0, sizeof(IP_ADAPTER_ADDRESSES));
u = sizeof(p);
GetAdaptersAddresses(0, GAA_FLAG_INCLUDE_PREFIX, NULL, p, &u);
p = (IP_ADAPTER_ADDRESSES*)HeapAlloc(GetProcessHeap(), 0, u);
ret = GetAdaptersAddresses(0, GAA_FLAG_INCLUDE_PREFIX, NULL, p, &u);
if (ret == NO_ERROR)
{
tp = p;
while (tp)
{
cout << "\nlength of ip adapter address";
tp->Length;
cout << "\nifindex (ipv4):" << tp->IfIndex;
cout << "\n Adapter name::" << tp->AdapterName;
PIP_ADAPTER_UNICAST_ADDRESS pu;
pu = tp->FirstUnicastAddress;
int i = 0;
cout << "\nunicast address:";
while (pu)
{
i++;
cout << "\nlength of sockaddr: " << (pu->Address).iSockaddrLength;
if (pu->Address.lpSockaddr->sa_family == AF_INET)
{
cout << "\n ipv4 addr:";
sockaddr_in *si = (sockaddr_in *)&(pu->Address.lpSockaddr);
char a[INET_ADDRSTRLEN];
inet_ntop(AF_INET, si, a, sizeof(a));
cout << a;
}
else if (pu->Address.lpSockaddr->sa_family == AF_INET6)
{
cout << "\n ipv6 addr:";
sockaddr_in6 *si = (sockaddr_in6 *)&(pu->Address.lpSockaddr);
char a[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, si, a, sizeof(a));
cout << a;
}
pu = pu->Next;
}
cout << "\n no of unicast address" << i;
PIP_ADAPTER_ANYCAST_ADDRESS pa;
i = 0;
pa = tp->FirstAnycastAddress;
cout << "\nanycast address:";
while (pa)
{
i++;
cout << "\nlength of sockaddr: " << (pa->Address).iSockaddrLength;
if (pa->Address.lpSockaddr->sa_family == AF_INET)
{
cout << "\n ipv4 addr:";
sockaddr_in *si = (sockaddr_in *)&(pa->Address.lpSockaddr);
char a[INET_ADDRSTRLEN];
inet_ntop(AF_INET, si, a, sizeof(a));
cout << a;
}
else if (pa->Address.lpSockaddr->sa_family == AF_INET6)
{
cout << "\n ipv6 addr:";
sockaddr_in6 *si = (sockaddr_in6 *)&(pa->Address.lpSockaddr);
char a[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, si, a, sizeof(a));
cout << a;
}
pa = pa->Next;
}
cout << "\n no of anycast address" << i;
PIP_ADAPTER_MULTICAST_ADDRESS pm;
i = 0;
pm = tp->FirstMulticastAddress;
cout << "\nmulticast address:";
while (pm)
{
i++;
cout << "\nlength of sockaddr: " << (pm->Address).iSockaddrLength;
if (pm->Address.lpSockaddr->sa_family == AF_INET)
{
cout << "\n ipv4 addr:";
sockaddr_in *si = (sockaddr_in *)&(pm->Address.lpSockaddr);
char a[INET_ADDRSTRLEN];
inet_ntop(AF_INET, si, a, sizeof(a));
cout << a;
}
else if (pm->Address.lpSockaddr->sa_family == AF_INET6)
{
cout << "\n ipv6 addr:";
sockaddr_in6 *si = (sockaddr_in6 *)&(pm->Address.lpSockaddr);
char a[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, si, a, sizeof(a));
cout << a;
}
pm = pm->Next;
}
cout << "\n no of multicast address" << i;
PIP_ADAPTER_DNS_SERVER_ADDRESS pd;
i = 0;
pd = tp->FirstDnsServerAddress;
cout << "\ndns address:";
while (pd)
{
i++;
cout << "\nlength of sockaddr: " << (pd->Address).iSockaddrLength;
if (pd->Address.lpSockaddr->sa_family == AF_INET)
{
cout << "\n ipv4 addr:";
sockaddr_in *si = (sockaddr_in *)&(pd->Address.lpSockaddr);
char a[INET_ADDRSTRLEN];
inet_ntop(AF_INET, si, a, sizeof(a));
cout << a;
}
else if (pd->Address.lpSockaddr->sa_family == AF_INET6)
{
cout << "\n ipv6 addr:";
sockaddr_in6 *si = (sockaddr_in6 *)&(pd->Address.lpSockaddr);
char a[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, si, a, sizeof(a));
cout << a;
}
pd = pd->Next;
}
cout << "\n no of dns server address" << i;
PIP_ADAPTER_GATEWAY_ADDRESS_LH pg;
i = 0;
pg = tp->FirstGatewayAddress;
cout << "\ngateway address:";
while (pg)
{
i++;
cout << "\nlength of sockaddr: " << (pg->Address).iSockaddrLength;
if (pg->Address.lpSockaddr->sa_family == AF_INET)
{
cout << "\n ipv4 addr:";
sockaddr_in *si = (sockaddr_in *)&(pg->Address.lpSockaddr);
char a[INET_ADDRSTRLEN];
inet_ntop(AF_INET, si, a, sizeof(a));
cout << a;
}
else if (pg->Address.lpSockaddr->sa_family == AF_INET6)
{
cout << "\n ipv6 addr:";
sockaddr_in6 *si = (sockaddr_in6 *)&(pg->Address.lpSockaddr);
char a[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, si, a, sizeof(a));
cout << a;
}
pg = pg->Next;
}
cout << "\ngateway address:" << i;
cout << "\n dns suffix" << tp->DnsSuffix;
cout << "\n description" << tp->Description;
cout << "\n friendly name" << tp->FriendlyName;
if (tp->PhysicalAddressLength != 0)
for (UINT i = 0; i < tp->PhysicalAddressLength; i++)
{
if (i == (tp->PhysicalAddressLength - 1))
cout << std::hex << (int)tp->PhysicalAddress[i];
else
cout << "-" << std::hex << (int)tp->PhysicalAddress[i];
}
cout << "\n Flags" << tp->Flags;
cout << "\nmtu" << tp->Mtu;
cout << "\n IfType" << tp->IfType;
cout << "\n OperStatus" << tp->OperStatus;
cout << "\n ipv6 ifindex :" << tp->Ipv6IfIndex;
cout << "\nand more";
tp = tp->Next;
}
}
else {
cout << "something went wrong";
}
HeapFree(GetProcessHeap(), 0, p);
p = NULL;
cin >> ret;
return 0;
}
如您所见,没有一个地址与命令提示符中的地址匹配。
最佳答案
我发现您的代码存在一些问题:
调用
GetAdaptersAddresses()
时,您没有执行足够的错误处理。您正在泄漏您分配的第一个
IP_ADAPTER_ADDRESSES
结构。您没有将
tp->Length
输出到while (tp)
循环顶部的控制台。您没有正确检索和格式化 IP 地址!
最后一点是问题的根源。
当您尝试从列表中检索 IP 地址时,您正在错误地访问 sockaddr_X
结构。
这段代码:
sockaddr_in *si = (sockaddr_in *)&(pu->Address.lpSockaddr);
sockaddr_in6 *si = (sockaddr_in6 *)&(pu->Address.lpSockaddr);
需要像这样:
sockaddr_in *si = (sockaddr_in *)(pu->Address.lpSockaddr);
sockaddr_in6 *si = (sockaddr_in6 *)(pu->Address.lpSockaddr);
lpSockaddr
字段已经是指向 sockaddr_X
结构的指针,因此您需要对该指针值进行类型转换,请勿使用&
运算符来获取该指针本身的地址,您将转换错误的内存地址,因此您尝试为 IP 地址格式化的二进制数据是垃圾!
您还错误地调用了inet_ntop()
。它需要一个指向 in_addr
/in6_addr
结构体的指针作为输入,但您向其传递一个指向 sockaddr_in
/sockaddr_in6< 的指针
结构代替。所以格式化的输出字符串也是垃圾!
这段代码:
inet_ntop(AF_INET, si, a, sizeof(a));
inet_ntop(AF_INET6, si, a, sizeof(a));
需要像这样:
inet_ntop(AF_INET, &(si->sin_addr), a, sizeof(a));
inet_ntop(AF_INET6, &(si->sin6_addr), a, sizeof(a));
对于链接列表中的所有任播、单播、多播、DNS 服务器和网关 IP 地址,您都犯了这两个错误。
话虽如此,尝试更多类似这样的事情:
// getadaptersinfo.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <WinSock2.h>
#include <iphlpapi.h>
#include <ws2tcpip.h>
#include <iostream>
#pragma comment(lib,"IPHLPAPI.lib")
#pragma comment(lib,"Ws2_32.lib")
using namespace std;
void displayAddress(const SOCKET_ADDRESS &Address)
{
cout << "\n Length of sockaddr: " << Address.iSockaddrLength;
if (Address.lpSockaddr->sa_family == AF_INET)
{
sockaddr_in *si = (sockaddr_in *)(Address.lpSockaddr);
char a[INET_ADDRSTRLEN] = {};
if (inet_ntop(AF_INET, &(si->sin_addr), a, sizeof(a)))
cout << "\n IPv4 address: " << a;
}
else if (Address.lpSockaddr->sa_family == AF_INET6)
{
sockaddr_in6 *si = (sockaddr_in6 *)(Address.lpSockaddr);
char a[INET6_ADDRSTRLEN] = {};
if (inet_ntop(AF_INET6, &(si->sin6_addr), a, sizeof(a)))
cout << "\n IPv6 address: " << a;
}
}
int main()
{
cout << "\nUsing GetAdaptersAddresses";
ULONG size = 1024 * 15;
PIP_ADAPTER_ADDRESSES p = (IP_ADAPTER_ADDRESSES*) HeapAlloc(GetProcessHeap(), 0, size);
if (!p)
{
cout << "\nCannot allocate memory";
cin.get();
return -1;
}
ULONG ret;
do
{
ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, p, &size);
if (ret != ERROR_BUFFER_OVERFLOW)
break;
PIP_ADAPTER_ADDRESSES newp = (IP_ADAPTER_ADDRESSES*) HeapReAlloc(GetProcessHeap(), 0, p, size);
if (!newp)
{
cout << "\nCannot reallocate memory";
HeapFree(GetProcessHeap(), 0, p);
cin.get();
return -1;
}
p = newp;
}
while (true);
if (ret != NO_ERROR)
{
cout << "\nSomething went wrong. Error: " << ret;
HeapFree(GetProcessHeap(), 0, p);
cin.get();
return -1;
}
int i = 0;
for(PIP_ADAPTER_ADDRESSES tp = p; tp != NULL; tp = tp->Next)
{
++i;
cout << "\nLength of IP Adapter info: " << tp->Length;
cout << "\n IPv4 IfIndex: " << tp->IfIndex;
cout << "\n Adapter name: " << tp->AdapterName;
cout << "\n Unicast addresses:";
int j = 0;
for (PIP_ADAPTER_UNICAST_ADDRESS pu = tp->FirstUnicastAddress; pu != NULL; pu = pu->Next)
{
++j;
displayAddress(pu->Address);
}
cout << "\n # of Unicast addresses: " << j;
cout << "\n Anycast addresses:";
j = 0;
for (PIP_ADAPTER_ANYCAST_ADDRESS pa = tp->FirstAnycastAddress; pa != NULL; pa = pa->Next)
{
++j;
displayAddress(pa->Address);
}
cout << "\n # of Anycast addresses: " << j;
cout << "\n Multicast addresses:";
j = 0;
for (PIP_ADAPTER_MULTICAST_ADDRESS pm = tp->FirstMulticastAddress; pm != NULL; pm = pm->Next)
{
++j;
displayAddress(pm->Address);
}
cout << "\n # of Multicast addresses: " << j;
cout << "\n DNS server addresses:";
j = 0;
for (PIP_ADAPTER_DNS_SERVER_ADDRESS pd tp->FirstDnsServerAddress; pd != NULL; pd = pd->Next)
{
++j;
displayAddress(pd->Address);
}
cout << "\n # of DNS server addresses: " << j;
cout << "\n Gateway addresses:";
j = 0;
for (PIP_ADAPTER_GATEWAY_ADDRESS_LH pg = tp->FirstGatewayAddress; pg != NULL; pg = pg->Next)
{
++j;
displayAddress(pg->Address);
}
cout << "\n # of Gateway addresses: " << j;
cout << "\n DNS suffix" << tp->DnsSuffix;
cout << "\n Description" << tp->Description;
cout << "\n Friendly name" << tp->FriendlyName;
if (tp->PhysicalAddressLength != 0)
{
cout << "\n Physical address: ";
cout << std::hex << (int)tp->PhysicalAddress[0];
for (UINT i = 1; i < tp->PhysicalAddressLength; i++)
cout << "-" << std::hex << (int)tp->PhysicalAddress[i];
}
cout << "\n Flags" << tp->Flags;
cout << "\n MTU" << tp->Mtu;
cout << "\n IfType" << tp->IfType;
cout << "\n OperStatus" << tp->OperStatus;
cout << "\n IPv6 IfIndex :" << tp->Ipv6IfIndex;
cout << "\n and more...";
}
cout << "\n# of IP Adapters: " << i;
HeapFree(GetProcessHeap(), 0, p);
cin.get();
return 0;
}
关于c++ - GetAdaptersAddresses() 未给出正确的 IP 地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49735517/