GetAdaptersAddresses()没有提供正确的IP地址

时间:2018-04-09 14:35:43

标签: c++ c sockets visual-c++ network-programming

我正在使用USB Internet加密狗,为我的计算机分配IPv6地址。当我使用onClicked: list.currentIndex += 1 时,我可以看到分配的IPv6地址,它是一个公共IP。

当我使用GetAdaptersAddresses()时,我得到一个包含任意广播,多播和单播地址的长链表,但它们都不匹配系统的IP地址。

还有其他地方可以获得系统的IP吗?我实际上想要获取系统的IP地址,以便我可以将它绑定到套接字。

我使用的是Windows 7。

touch

image

如您所见,没有一个地址与命令提示符中的地址匹配。

2 个答案:

答案 0 :(得分:2)

我发现您的代码存在许多问题:

  • 调用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;
}

答案 1 :(得分:-1)

此代码:

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);