• windows 获取本机(全部)IPv4、IPv6、MAC地址方法 (C/C++)


    windows下获取IP地址的两种方法;

    一种可以获取IPv4和IPv6,但是需要WSAStartup;

    一种只能取到IPv4,但是不需要WSAStartup;

    如下:

    方法一:(可以获取IPv4和IPv6)

    #define _WINSOCK_DEPRECATED_NO_WARNINGS
    #include <Winsock2.h>
    #include <stdio.h>
    #include <iostream>
    #include <cstring>
    #include<ws2tcpip.h>
    #pragma comment(lib, "ws2_32.lib ")  //linking to the library
    using namespace std;
    int get_ip()
    {
        struct addrinfo *ailist, *aip;
        struct addrinfo hint;
        struct sockaddr_in6 *sinp6;
        PHOSTENT hostinfo;
        char hostname[255] = {0}; //主机名
        char *port = "3294";      //端口号
        const char *addr;
        int ilRc;
        gethostname(hostname, sizeof(hostname));
        if((hostinfo = gethostbyname(hostname)) == NULL) //获得本地ipv4地址
        {
            errno = GetLastError();
            fprintf(stderr,"gethostbyname Error:%d
    ", errno);
            return 1;
        }
        LPCSTR ip;
        while(*(hostinfo->h_addr_list) != NULL) //输出ipv4地址
        {
            ip = inet_ntoa(*(struct in_addr *) *hostinfo->h_addr_list);
            printf("ipv4 addr = %s
    
    ", ip);
            hostinfo->h_addr_list++;
        }
        hint.ai_family = AF_INET6;        //hint 的限定设置
        hint.ai_socktype = SOCK_STREAM;   //这里可是设置 socket type    比如  SOCK_DGRAM
        hint.ai_flags = AI_PASSIVE;       // flags 的标志很多。常用的有AI_CANONNAME;
        hint.ai_protocol = 0;             //设置协议  一般为0,默认
        hint.ai_addrlen = 0;              //下面不可以设置,为0,或者为NULL
        hint.ai_canonname = NULL;
        hint.ai_addr = NULL;
        hint.ai_next = NULL;
        ilRc = getaddrinfo(hostname, port, &hint, &ailist); //通过主机名获得地址信息
        if (ilRc < 0)
        {
            char str_error[100];
            strcpy(str_error, (char *)gai_strerror(errno));
            printf("str_error = %s", str_error);
            return 0;
        }
        if(ailist == NULL)
        {
            printf("sorry not find the IP address,please try again 
    ");
        }
        for (aip = ailist; aip != NULL; aip = aip->ai_next) //显示获取的信息
        {
            aip->ai_family == AF_INET6;
            sinp6 = (struct sockaddr_in6 *)aip->ai_addr;    //为什么是for 循环 ,先向下看
            int i;
            printf("ipv6 addr = ");
            for(i = 0; i < 16; i++)
            {
                if(((i-1)%2) && (i>0))
                {
                    printf(":");
                }
                printf("%02x",sinp6->sin6_addr.u.Byte[i]);
            }
            printf(" 
    ");
            printf(" 
    ");
        }
        while(1);
    }
    int main(){
    
        WORD wVersionRequested;
        WSADATA wsaData;
        int err;
        wVersionRequested = MAKEWORD( 1, 1 );
        err = WSAStartup( wVersionRequested, &wsaData );//initiate the ws2_32.dll and match the version
        if ( err != 0 )
        {
            return 0;
        }
        if ( LOBYTE( wsaData.wVersion ) != 1 ||   //if the version is not matched ,then quit and terminate the ws3_32.dll
            HIBYTE( wsaData.wVersion ) != 1 )
        {
            WSACleanup( );
            return 0;
        }
        get_ip();
        WSACleanup( );
        return 0;
    }

    方法二:(只能取到IPv4)

    //#define _WINSOCK_DEPRECATED_NO_WARNINGS
    #include <WinSock2.h>
    #include <Iphlpapi.h>
    #include <iostream>
    using namespace std;
    #pragma comment(lib,"Iphlpapi.lib") //需要添加Iphlpapi.lib库
    //#pragma comment(lib, "ws2_32.lib")
    
    int main(int argc, char* argv[])
    {
        //PIP_ADAPTER_INFO结构体指针存储本机网卡信息
        PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO();
        //得到结构体大小,用于GetAdaptersInfo参数
        unsigned long stSize = sizeof(IP_ADAPTER_INFO);
        //调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量;其中stSize参数既是一个输入量也是一个输出量
        int nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
        //记录网卡数量
        DWORD netCardNum = 0;
        GetNumberOfInterfaces(&netCardNum);
        cout << "网卡数量:" << netCardNum<< endl; netCardNum = 0;
        //记录每张网卡上的IP地址数量
        int IPnumPerNetCard = 0;
        if (ERROR_BUFFER_OVERFLOW == nRel)
        {
            //如果函数返回的是ERROR_BUFFER_OVERFLOW
            //则说明GetAdaptersInfo参数传递的内存空间不够,同时其传出stSize,表示需要的空间大小
            //这也是说明为什么stSize既是一个输入量也是一个输出量
            //释放原来的内存空间
            delete pIpAdapterInfo;
            //重新申请内存空间用来存储所有网卡信息
            pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[stSize];
            //再次调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量
            nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
        }
        if (ERROR_SUCCESS == nRel)
        {
            //输出网卡信息
            //可能有多网卡,因此通过循环去判断
            while (pIpAdapterInfo)
            {
                cout << "网卡序号:" << ++netCardNum <<"	"<<pIpAdapterInfo->Index << endl;
                cout << "网卡名称:" << pIpAdapterInfo->AdapterName << endl;
                cout << "网卡描述:" << pIpAdapterInfo->Description << endl;
                cout << "网卡类型:";
                switch (pIpAdapterInfo->Type)
                {
                case MIB_IF_TYPE_OTHER:        cout << "OTHER" << endl; break;
                case MIB_IF_TYPE_ETHERNET:    cout << "ETHERNET" << endl; break;
                case MIB_IF_TYPE_TOKENRING:    cout << "TOKENRING" << endl; break;
                case MIB_IF_TYPE_FDDI:        cout << "FDDI" << endl; break;
                case MIB_IF_TYPE_PPP:        cout << "PPP" << endl; break;
                case MIB_IF_TYPE_LOOPBACK:    cout << "LOOPBACK" << endl; break;
                case MIB_IF_TYPE_SLIP:        cout << "SLIP" << endl; break;
                default:                    cout << "" << endl; break;
                }
                cout << "网卡MAC地址:";
                for (DWORD i = 0; i < pIpAdapterInfo->AddressLength; i++)
                    if (i < pIpAdapterInfo->AddressLength - 1)
                    {
                        printf("%02X-", pIpAdapterInfo->Address[i]);
                    }
                    else
                    {
                        printf("%02X
    ", pIpAdapterInfo->Address[i]);
                    }
                cout << "网卡IP地址如下:" << endl;
                IPnumPerNetCard = 0;
                //可能网卡有多IP,因此通过循环去判断
                IP_ADDR_STRING *pIpAddrString = &(pIpAdapterInfo->IpAddressList);
                do
                {
                    cout << "该网卡上的IP数量:" << ++IPnumPerNetCard << endl;
                    cout << "IP 地址:" << pIpAddrString->IpAddress.String << endl;
                    cout << "子网掩码:" << pIpAddrString->IpMask.String << endl;
                    cout << "网关地址:" << pIpAdapterInfo->GatewayList.IpAddress.String << endl;
                    pIpAddrString = pIpAddrString->Next;
                } while (pIpAddrString);
                pIpAdapterInfo = pIpAdapterInfo->Next;
                cout << "--------------------------------------------------------------------" << endl;
            }
    
        }
        //释放内存空间
        if (pIpAdapterInfo)
        {
            delete pIpAdapterInfo;
        }
        return 0;
    }
  • 相关阅读:
    谈谈 OC 中的内联函数
    Spring 新手教程(二) 生命周期和作用域
    实时竞价(RTB) 介绍(基础篇)
    oracle数据库性能优化方案精髓整理收集回想
    HNU 13411 Reverse a Road II(最大流+BFS)经典
    CSS3主要知识点复习总结+HTML5新增标签
    修改默认MYSQL数据库data存放位置
    mysql状态查看 QPS/TPS/缓存命中率查看
    Mysql5.7.10新加用户
    很靠谱linux常用命令
  • 原文地址:https://www.cnblogs.com/Fightingbirds/p/13680027.html
Copyright © 2020-2023  润新知