GetAdaptersAddresses() 没有给出正确的 IP 地址 [英] GetAdaptersAddresses() not giving correct IP address

查看:133
本文介绍了GetAdaptersAddresses() 没有给出正确的 IP 地址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 USB 互联网加密狗,它为我的计算机分配了一个 IPv6 地址.当我使用 ipconfig 时,我可以看到分配的 IPv6 地址,它是一个公共 IP.

当我使用

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

解决方案

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

  • 您在调用 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 struct 代替.所以格式化的输出字符串也是垃圾!

此代码:

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 :定义控制台应用程序的入口点.//#include "stdafx.h"#include #include #include #include #pragma 注释(lib,"IPHLPAPI.lib")#pragma 注释(lib,"Ws2_32.lib")使用命名空间标准;void displayAddress(const SOCKET_ADDRESS &Address){cout<<"\n sockaddr 的长度:" <<地址.iSockaddrLength;if (Address.lpSockaddr->sa_family == AF_INET){sockaddr_in *si = (sockaddr_in *)(Address.lpSockaddr);字符 a[INET_ADDRSTRLEN] = {};if (inet_ntop(AF_INET, &(si->sin_addr), a, sizeof(a)))cout<<"\n IPv4 地址:" <<一种;}else if (Address.lpSockaddr->sa_family == AF_INET6){sockaddr_in6 *si = (sockaddr_in6 *)(Address.lpSockaddr);字符 a[INET6_ADDRSTRLEN] = {};if (inet_ntop(AF_INET6, &(si->sin6_addr), a, sizeof(a)))cout<<"\n IPv6 地址:" <<一种;}}int main(){cout<<"\n使用 GetAdaptersAddresses";超长尺寸 = 1024 * 15;PIP_ADAPTER_ADDRESSES p = (IP_ADAPTER_ADDRESSES*) HeapAlloc(GetProcessHeap(), 0, size);如果(!p){cout<<"\n无法分配内存";cin.get();返回-1;}乌龙 ret;做{ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, p, &size);if (ret != ERROR_BUFFER_OVERFLOW)休息;PIP_ADAPTER_ADDRESSES newp = (IP_ADAPTER_ADDRESSES*) HeapReAlloc(GetProcessHeap(), 0, p, size);如果(!newp){cout<<"\n无法重新分配内存";HeapFree(GetProcessHeap(), 0, p);cin.get();返回-1;}p = 新 p;}同时(真);如果(ret != NO_ERROR){cout<<"\n出了点问题.错误:" <<退;HeapFree(GetProcessHeap(), 0, p);cin.get();返回-1;}int i = 0;for(PIP_ADAPTER_ADDRESSES tp = p; tp != NULL; tp = tp->Next){++i;cout<<"\nIP 适配器信息的长度:" <<tp->长度;cout<<"\n IPv4 IfIndex: " <<tp->IfIndex;cout<<"\n 适配器名称:" <<tp->适配器名称;cout<<"\n 单播地址:";int j = 0;for (PIP_ADAPTER_UNICAST_ADDRESS pu = tp->FirstUnicastAddress; pu != NULL; pu = pu->Next){++j;显示地址(pu->地址);}cout<<"\n # 单播地址:" <<j;cout<<"\n 任播地址:";j = 0;for (PIP_ADAPTER_ANYCAST_ADDRESS pa = tp->FirstAnycastAddress; pa != NULL; pa = pa->Next){++j;显示地址(pa->地址);}cout<<"\n # 个任播地址:" <<j;cout<<"\n 多播地址:";j = 0;for (PIP_ADAPTER_MULTICAST_ADDRESS pm = tp->FirstMulticastAddress; pm != NULL; pm = pm->Next){++j;显示地址(下午->地址);}cout<<"\n # 组播地址:" <<j;cout<<"\n DNS 服务器地址:";j = 0;for (PIP_ADAPTER_DNS_SERVER_ADDRESS pd tp->FirstDnsServerAddress; pd != NULL; pd = pd->Next){++j;显示地址(pd->地址);}cout<<"\n # DNS 服务器地址:" <<j;cout<<"\n 网关地址:";j = 0;for (PIP_ADAPTER_GATEWAY_ADDRESS_LH pg = tp->FirstGatewayAddress; pg != NULL; pg = pg->Next){++j;显示地址(pg->地址);}cout<<"\n # 网关地址:" <<j;cout<<"\n DNS 后缀" <<tp->DnsSuffix;cout<<"\n 说明" <<tp->描述;cout<<"\n 友好名称" <<tp->FriendlyName;if (tp->PhysicalAddressLength != 0){cout<<"\n 物理地址:";cout<<std::hex <<(int)tp->PhysicalAddress[0];for (UINT i = 1; i PhysicalAddressLength; i++)cout<<-"<<std::hex <<(int)tp->PhysicalAddress[i];}cout<<"\n 标志" <<tp->标志;cout<<"\n MTU" <<tp->Mtu;cout<<"\n IfType" <<tp->IfType;cout<<"\n 操作状态" <<tp->操作状态;cout<<"\n IPv6 IfIndex :" <<tp->Ipv6IfIndex;cout<<"\n 和更多...";}cout<<"\n# 的 IP 适配器:" <<一世;HeapFree(GetProcessHeap(), 0, p);cin.get();返回0;}

I am using a USB Internet dongle that assigns an IPv6 address to my computer. When I use ipconfig, I can see the IPv6 address assigned, it's a public IP.

When I use GetAdaptersAddresses(), I get a long linked list of anycast, multicast, and unicast addresses, but none of them match the system's IP address.

Is there some other place where I would get system's IP? I actually want to get the IP address of the system so that I can bind it to a socket.

I use 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;
}

As you can see, none of the addresses match the address in the command prompt.

解决方案

I see a number of problems with your code:

  • you are not performing adequate error handling when calling GetAdaptersAddresses().

  • you are leaking the first IP_ADAPTER_ADDRESSES struct that you allocate.

  • you are not outputting tp->Length to the console at the top of your while (tp) loop.

  • you are not retrieving and formatting the IP addresses correctly!

That last point is the root of your problem.

When you attempt to retrieve an IP address from the list, you are accessing the sockaddr_X struct incorrectly.

This code:

sockaddr_in *si = (sockaddr_in *)&(pu->Address.lpSockaddr);

sockaddr_in6 *si = (sockaddr_in6 *)&(pu->Address.lpSockaddr);

Needs to be like this instead:

sockaddr_in *si = (sockaddr_in *)(pu->Address.lpSockaddr);

sockaddr_in6 *si = (sockaddr_in6 *)(pu->Address.lpSockaddr);

The lpSockaddr field is already a pointer to a sockaddr_X struct, so you need to type-cast that pointer value, DO NOT use the & operator to take the address of that pointer itself, you would be type-casting the wrong memory address and so the binary data you attempt to format for the IP address is garbage!

You are also calling inet_ntop() incorrectly. It expects a pointer to a in_addr/in6_addr struct as input, but you are passing it a pointer to a sockaddr_in/sockaddr_in6 struct instead. So the formatted output strings are garbage as well!

This code:

inet_ntop(AF_INET, si, a, sizeof(a));

inet_ntop(AF_INET6, si, a, sizeof(a));

Needs to be like this instead:

inet_ntop(AF_INET, &(si->sin_addr), a, sizeof(a));

inet_ntop(AF_INET6, &(si->sin6_addr), a, sizeof(a));

You are making these 2 mistakes for all of the anycast, unicast, multicast, DNS server, and gateway IP addresses in the linked lists.

With that said, try something more like this:

// 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;
}

这篇关于GetAdaptersAddresses() 没有给出正确的 IP 地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆