QT---Winsocket获取网关(Gateway) 主机IP等信息

  基于WinPcap库做开发,需要利用到局域网的默认网关地址和Mac地址,但是WinPcap实现获取网关IP地址没有很好的思路,可以知道的是网关的接收和发出的数据包数量一般是比局域网内的各主机要多的,可以抓包,判断,根据这个来获取网关的IP地址和Mac地址。不过,这不可靠。 
  很快就知道利用WinSocket里面的库可以获取网关的IP地址,实验前包含必要的头文件(

// 获取Host IP(通过winsock2)
QString PcapCommon::getHostIpByWinSock()
{
    char hostname[256] = {0};
    WSADATA wsaData;
    char ip[128] = {0};

    // 调用Windows Sockets DLL
    if (WSAStartup(MAKEWORD(2,1),&wsaData)){
        printf("Winsock无法初始化!\n");
        WSACleanup();
        return 0;
    }

    if(gethostname(hostname, sizeof(hostname)) == 0){
        // 结构
        struct hostent * pHost;
        pHost = gethostbyname(hostname);
        // 只取主网卡 ip
        BYTE *p;
        p =(BYTE *)pHost->h_addr;
        sprintf(ip,"%d.%d.%d.%d", p[0], p[1],p[2], p[3]);
    }

    return QString(ip);
}
获取完主机IP地址后,再获取网关(Gateway)的IP地址
// 获取本机网关(通过winsock2)
QString PcapCommon::getGateway()
{
    PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO();
    unsigned long stSize = sizeof(IP_ADAPTER_INFO);
    int nRel = GetAdaptersInfo(pIpAdapterInfo,&stSize);
    if (ERROR_BUFFER_OVERFLOW == nRel){
        // ERROR_BUFFER_OVERFLOW:内存空间不够
        // 释放原来的内存空间
        delete pIpAdapterInfo;
        // 重新申请内存空间用来存储所有网卡信息
        pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[stSize];
        // 再次调用GetAdaptersInfo
        nRel=GetAdaptersInfo(pIpAdapterInfo,&stSize);
    }
    if (ERROR_SUCCESS == nRel){
        while (pIpAdapterInfo){
            switch(pIpAdapterInfo->Type){
            case MIB_IF_TYPE_OTHER:
                break;
            case MIB_IF_TYPE_ETHERNET:
                break;
            case MIB_IF_TYPE_TOKENRING:
                break;
            case MIB_IF_TYPE_FDDI:
                break;
            case MIB_IF_TYPE_PPP:
                break;
            case MIB_IF_TYPE_LOOPBACK:
                break;
            case MIB_IF_TYPE_SLIP:
                break;
            default:
                break;
            }
            for (DWORD i = 0; i < pIpAdapterInfo->AddressLength; i++)
                if (i < pIpAdapterInfo->AddressLength-1){
                }
                else{                    
                }                
                // 多个网卡、多个IP
                IP_ADDR_STRING *pIpAddrString =&(pIpAdapterInfo->IpAddressList);
                do{                    
                    if(QString(pIpAddrString->IpAddress.String) == getHostIpByWinSock()){                        
                        return QString(pIpAdapterInfo->GatewayList.IpAddress.String);
                    }                    
                    pIpAddrString=pIpAddrString->Next;
                } while (pIpAddrString);
                pIpAdapterInfo = pIpAdapterInfo->Next;               
        }

    }
    //释放内存空间
    if (pIpAdapterInfo){
        delete pIpAdapterInfo;
    }

    return "0.0.0.0";
}

  上面的循环是因为有多个网卡,循环列出各个网卡,思路是找到其中的一个网卡的IP地址是跟主机的IP地址是一样的,那么就将该网卡中的网关信息返回,在这里,还可以获取该网卡其他的信息,比如本机Mac地址,掩码地址等,但是这里是不能获取网关的Mac地址的,接下来就通过WinPcap来获取IP地址是网关的IP地址的包,并得到网关的Mac地址,这样就得到了网关的IP地址和Mac地址

  怎么用WinPcap去抓包,这里就不介绍了。可以参考WinPcap中文技术文档:

http://www.ferrisxu.com/WinPcap/html/

测试帮助:

route print : 查看路由表信息,可以看到网关信息

这里写图片描述

上述的两段代码调试信息(程序中为了精简,没有打印出):

这里写图片描述

 
 
http://blog.csdn.net/freeape/article/details/50908911
posted @   findumars  Views(2803)  Comments(0Edit  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
历史上的今天:
2016-01-17 Delphi 全面控制Windows任务栏
2014-01-17 WndProc漏写override会发生什么情况?
点击右上角即可分享
微信分享提示