windows下用c++获取本机ip地址

来源:互联网 发布:淘宝客推广位怎么设置 编辑:程序博客网 时间:2024/06/04 18:48

windows下用c++获取本机ip地址

工作过程中遇到一个需求,需要获取本机ip地址,同时获取本机网络连接情况,即网线是否连接。

经过多番搜索,有如下3种方案。

1、管道+多进程

思路:在一个cmd中执行ipconfig并获取其输出。

代码如下:

#ifndef CMDEXC_H#define CMDEXC_H#include <string>class CmdExc{public:    CmdExc(std::string cmd,std::string mode="rt");    virtual ~CmdExc();    std::string getOutput() const;private:    std::string m_strOutput__;    FILE* m_fp__;};CmdExc::CmdExc(std::string cmd, std::string mode){    m_fp__=_popen(cmd.c_str(),mode.c_str());    char buf[256]={0};    if(NULL != m_fp__){        int read_len;        while((read_len=fread(buf,sizeof(buf)-1,1,m_fp__))>0){            m_strOutput__+=buf;            memset(buf,0,sizeof(buf));        }    }}CmdExc::~CmdExc(){    if(NULL != m_fp__){        _pclose(m_fp__);    }}std::string CmdExc::getOutput() const{    return m_strOutput__;}#endif // CMDEXC_H

调用处代码

CmdExc cmd("ipconfig");cout<<cmd.getOutput().c_str()<<endl;

缺点:

  • 多进程
  • 会有cmd的黑框一闪而过
  • 网线未插时无法获取到ip配置
  • 很坑爹的在MFC工程中没法用,必须是控制台的应用。如win32工程,或者Qt工程下,都没问题的。官方的解释是窗口工程需要用CreateProcess来创建进程实现功能。

优点:

  • 可以知道是否插了网线。。。。因为没插就没有显示。。。

2、iphlpapi.lib

思路:使用iphlpapi库

使用iphlpapi中的GetAdaptersInfo函数来获取各个网卡的信息。

代码如下:

代码来自于官网msdn。个人稍加修改简化。官方链接。

std::vector<string> IpDealer::getAdptInfo() {    vector<string> result;    IP_ADAPTER_INFO *pAdpFree=NULL;    IP_ADAPTER_INFO *pIpAdpInfo=(IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO));    unsigned long ulBufLen=sizeof(IP_ADAPTER_INFO);    int ret;    //第一次调用获取需要开辟的内存空间大小    if((ret=GetAdaptersInfo(pIpAdpInfo,&ulBufLen))==ERROR_BUFFER_OVERFLOW){        free(pIpAdpInfo);        //分配实际所需要的内存空间        pIpAdpInfo=(IP_ADAPTER_INFO*)malloc(ulBufLen);        if(NULL == pIpAdpInfo){            return result;        }    }    char ip[256];    if((ret=GetAdaptersInfo(pIpAdpInfo,&ulBufLen))==NO_ERROR){        pAdpFree=pIpAdpInfo;        for(int i=0;pIpAdpInfo;i++){            string addr;            snprintf(ip,sizeof(ip),"netcard%d ip addr:",i);            addr+=ip;            IP_ADDR_STRING *pIps=&pIpAdpInfo->IpAddressList;            while(pIps){                snprintf(ip,sizeof(ip),"ip:%s,mask:%s,gate:%s.",pIps->IpAddress.String,                         pIps->IpMask.String,pIpAdpInfo->GatewayList.IpAddress.String);                addr+=ip;                cout<<pIps->IpAddress.String<<endl;                cout<<pIps->IpMask.String<<endl;                cout<<pIpAdpInfo->GatewayList.IpAddress.String<<endl;                pIps=pIps->Next;            }            result.push_back(addr);            pIpAdpInfo=pIpAdpInfo->Next;        }    }    if(pAdpFree){        free(pAdpFree);    }    return result;}

缺点:

  • 稍微有些复杂
  • 如果是vc6,默认是不带iphlpapi.lib这个库的。。。。需要手动安装sdk。。。200来M。。。Qt5.2、vs2010均有这个库。

优点:

  • 可以知道网线连没连,没连,获取到的是0.0.0.0。。。。

3、gethostbyname

思路:使用gethostbyname相关函数

代码如下:

std::vector<std::string> IpDealer::getIpList(){    std::vector<std::string> result;    char name[256];    int getNameRet=gethostname(name,sizeof(name));    hostent *host=gethostbyname(name);    if(NULL == host){        return result;    }    in_addr *pAddr=(in_addr*)*host->h_addr_list;    for(int i=0;i<(strlen((char*)*host->h_addr_list)-strlen(host->h_name) )/4 && pAddr;i++){        string addr=inet_ntoa(pAddr[i]);        cout<<addr.c_str()<<endl;        result.push_back(addr);    }    return result;}

缺点:

  • 网线没插时获取到的ip是127.0.0.1。
  • 获取ip个数时不够清晰,因为hostent结构中h_addr_list是一个\0结尾的字符串,但是长度不是4的整数倍。。。。。因为最后附加了hostname字符串。。。。但是官网并未明说。。。我是从代码中断点看出来的。。。稍微有些坑

优点:

  • 实现较简单

详细源代码见我的gitee。

原创粉丝点击