有时候,老板会提出一些奇怪的需求,比如说获取本机IP和mac,并显示在界面中,还就显示一个。
一般情况下,我们会有多个网卡,一个网卡会有多个IP,所以一般情况下,很难获取到老板觉得对的那个IP。
所以,鄙人参考了这位兄台VC++获取路由表_尹成的技术博客-CSDN博客 的博客,通过查找路由表的方式,获取老板想要的那个IP。
原理很简单,比如我要访问www.baidu.com,驱动会去路由表进行查找,然后决定从哪个网卡把报文发出去。我模拟的就是这个流程。
用目的IP和路由表的IP分别与子网掩码mask进行与操作,若相等则证明匹配到了路由,即知道了出接口。鄙人使用Qt的接口很方便的通过interface Index获取到了相应的网卡信息。interface index 可以理解为当前机器网卡(其实不止是网卡)的唯一索引,诸位若不喜欢Qt也可以通过其他方法根据interface index获取网卡信息。
代码如下:
#include <windows.h>
#include <IPHlpApi.h>
//鄙人用的QT,大家可以用自己喜欢的
#include <QNetWorkInterface>
#include <QDebug>
#pragma comment(lib, "Iphlpapi.lib")
#pragma comment(lib, "WS2_32.lib")
QString m_ip;
QString m_mac;
PMIB_IPFORWARDTABLE MyGetIpForwardTable(BOOL bOrder)
{
PMIB_IPFORWARDTABLE pIpRouteTab = NULL;
DWORD dwActualSize = 0;
// 查询所需缓冲区的大小
if(::GetIpForwardTable(pIpRouteTab, &dwActualSize, bOrder) == ERROR_INSUFFICIENT_BUFFER)
{
// 为MIB_IPFORWARDTABLE结构申请内存
pIpRouteTab = (PMIB_IPFORWARDTABLE)::GlobalAlloc(GPTR, dwActualSize);
// 获取路由表
if(::GetIpForwardTable(pIpRouteTab, &dwActualSize, bOrder) == NO_ERROR)
return pIpRouteTab;
::GlobalFree(pIpRouteTab);
}
return NULL;
}
void MyFreeIpForwardTable(PMIB_IPFORWARDTABLE pIpRouteTab)
{
if(pIpRouteTab != NULL)
::GlobalFree(pIpRouteTab);
}
static QString getGoodIP(QList<QNetworkAddressEntry> curList)
{
QString curIp = "";
for (int i = 0; i < curList.size(); i++)
{
if (curList.at(i).ip().toIPv4Address())
{
return curList.at(i).ip().toString();
}
}
return curIp;
}
void getIPAndMac()
{
QString ip = "www.baidu.com";
QHostAddress curAddress = QHostAddress(ip);
PMIB_IPFORWARDTABLE pIpRouteTable = MyGetIpForwardTable(TRUE);
if (pIpRouteTable != NULL)
{
for (INT i = pIpRouteTable->dwNumEntries - 1; i >= 0; i--)
{
// 子网掩码
ULONG mask = pIpRouteTable->table[i].dwForwardMask;
ULONG ip = pIpRouteTable->table[i].dwForwardDest;
// 网关地址
ULONG gateway = pIpRouteTable->table[i].dwForwardNextHop;
ULONG a = curAddress.toIPv4Address() & mask;
ULONG b = ip & mask;
//匹配到了路由表 获取该index 的 网卡信息
if (a == b)
{
QList<QNetworkInterface> nets = QNetworkInterface::allInterfaces();
for (int j = 0; j < nets.size(); j++)
{
if (nets.at(j).index() == pIpRouteTable->table[i].dwForwardIfIndex)
{
m_ip = getGoodIP(nets.at(j).addressEntries());
m_mac = nets.at(j).hardwareAddress();
MyFreeIpForwardTable(pIpRouteTable);
return;
}
}
}
}
}
MyFreeIpForwardTable(pIpRouteTable);
}
调用getIPAndMac 即可。