获取网卡上的IP、网关及DNS信息,获取最佳路由,遍历路由表中的条目(附源码)
- 软件开发
- 2025-08-18 04:09:02

VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...) blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...) blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具从入门到精通案例集锦(专栏文章正在更新中...) blog.csdn.net/chenlycly/article/details/131405795C/C++基础与进阶(专栏文章,持续更新中...) blog.csdn.net/chenlycly/category_11931267.html 我们可以通过调用系统API函数去获取机器上所有网卡的信息,可以获取到网卡上配置的IP、网关及DNS等信息。调用系统API可以获取最佳路由网卡,可以遍历系统路由表中的条目,可以看到默认路由和添加的策略路由。
1、获取系统中所有网卡的信息主要是通过调用系统API函数GetAdaptersInfo来获取网卡上配置的IP、网关、DNS等信息,相关代码如下:
// 获取所有网卡信息 void GetNetAdaptersInfo { // IP路由表 ULONG ulOutBufLen = NULL; PMIB_IPFORWARDTABLE pIpForwardTable = NULL; GetIpForwardTable( pIpForwardTable, &ulOutBufLen, TRUE ); pIpForwardTable = (PMIB_IPFORWARDTABLE)malloc( ulOutBufLen ); if ( NULL != pIpForwardTable ) { // 找到最佳路由,读出对应的IP索引 if ( NO_ERROR == GetIpForwardTable( pIpForwardTable, &ulOutBufLen, FALSE ) ) { } } DWORD dwRetVal = 0; PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *) malloc( sizeof(IP_ADAPTER_INFO) ); unsigned long ulOutBufLen = sizeof(IP_ADAPTER_INFO); // 试探以下buffer长度够不够 if (GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS) { free(pAdapterInfo); pAdapterInfo = (IP_ADAPTER_INFO *) malloc (ulOutBufLen); } PIP_ADAPTER_INFO pAdapter = NULL; if ((dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { int nIndex = 0; pAdapter = pAdapterInfo; while (pAdapter != NULL ) { // 1、读出网卡名称 CString szAdapter; szAdapter.Format( _T("第%d块网卡:"), nIndex + 1); szAdapter += pAdapter->Description; // 2、网卡上所有IP信息 IP_ADDR_STRING *pIPStr = &(pAdapter->IpAddressList); for( ; pIPStr != NULL; ) { szAdapter += _T("\r\n"); s8* byIpAddr = pIPStr->IpAddress.String; szAdapter += _T("IP: "); szAdapter += byIpAddr; szAdapter += _T(" "); szAdapter += STRING_MASK; s8 *byMaskAddr = pIPStr->IpMask.String; szAdapter += byMaskAddr; // 寻找IP对应的跳数 for ( u32 dw = 0; dw < pIpForwardTable->dwNumEntries; dw++ ) { CString szRoute; IN_ADDR inDest; inDest.S_un.S_addr = pIpForwardTable->table[dw].dwForwardDest; if ( inet_ntoa( ntohl(inDest.S_un.S_addr) ) == (CString)byIpAddr ) { CString szMetric; szMetric = _T(" "); CString strTemp; strTemp.Format( _T("跳数:"), pIpForwardTable->table[dw].dwForwardMetric1 ); szMetric += strTemp; szAdapter += szMetric; } } pIPStr = pIPStr->Next; } // 3、网卡上的网关信息 IP_ADDR_STRING *pGatewayStr = &(pAdapter->GatewayList); for( ; pGatewayStr != NULL; ) { szAdapter +=_T( " " ); s8* byGwAddr = pGatewayStr->IpAddress.String; szAdapter += STRING_GATEWAY; szAdapter += byGwAddr; pGatewayStr = pGatewayStr->Next; } // 4、网卡上的DNS信息: TCHAR achDnsInfo[MAX_PATH] = {0}; CString szSubKey = _T("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\"); szSubKey += CopyUtf8ToCStringT( pAdapter->AdapterName ); HKEY hKey = NULL; LONG lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, (LPCTSTR)szSubKey, 0, KEY_READ, &hKey ); if ( lRet == ERROR_SUCCESS ) { DWORD dwSize = MAX_PATH; DWORD dwType = REG_SZ; lRet = RegQueryValueEx( hKey, _T("NameServer"), NULL, &dwType, (LPBYTE)achDnsInfo, &dwSize ); CString szDns; CString strDnsInfo = achDnsInfo; if ( _tcscmp( strDnsInfo, _T("") ) != 0 ) { szDns.Format( _T("DNS服务器: %s"), strDnsInfo ); } szAdapter += szDns; RegCloseKey( hKey ); } pAdapter = pAdapter->Next; } } if ( pIpForwardTable != NULL ) { free( pIpForwardTable ); } if ( pAdapterInfo != NULL ) { free( pAdapterInfo ); } } 2、获取最佳路由网卡调用系统API函数GetBestInterface,传入要访问的目标IP,如下所示:
// 获取最佳路由对应的网卡索引号 DWORD dwResult = GetBestInterface(inet_addr(pDestIp), &dwBestIndex);GetBestInterface函数返回后,返回的dwBestIndex值,就是最佳路由网卡的序号。
获取最佳路由网卡,一般是用在多网卡的机器上,比如一张是连外网的网卡,一张是连局域网的网卡。在Windows系统中,不管插有多少张网卡,只能设置一个默认网关,即只能在一个网卡上设置网关,其他网卡不能设置网关。没设置网关的,可以通过添加策略路由去解决路由问题。
有一点需要注意的是,系统选择的最佳路由可能是有问题的,比如我访问一个内网的地址,结果系统选择走外网的网卡,这就需要我们人为地去干预了。
3、遍历系统路由表,获取最佳路由在Windows系统中,可以在cmd中输入route print命令查看系统的路由表,如下所示:
我们可以通过调用系统API函数GetIpForwardTable去遍历路由表中的条目。比如如下的代码,代码中通过访问的目标地址,到路由表中找一个对应的路由:
// 传入要访问的目标IP,在路由表条目中找到最佳路由 BOOL FindBestRouteEntry( DWORD dwDestIp) { PMIB_IPFORWARDTABLE pIpForwardTable = NULL; DWORD dwActualSize = 0; DWORD dwRst = NO_ERROR; // 获取系统路由表 dwRst = ::GetIpForwardTable( pIpForwardTable, &dwActualSize, TRUE ); if( NO_ERROR != dwRst) { if ( ERROR_INSUFFICIENT_BUFFER == dwRst) { pIpForwardTable = (PMIB_IPFORWARDTABLE)malloc(dwActualSize); if (NO_ERROR != GetIpForwardTable( pIpForwardTable, &dwActualSize, TRUE)) { free(pIpForwardTable); return FALSE; } } else { return FALSE; } } else { assert(FALSE); } // 遍历系统路由表条目,根据目标地址确定使用哪条路由,然后获取该条路由 // 对应的网关 for(DWORD i = 0; i < pIpForwardTable->dwNumEntries; i++) { DWORD dwForwardDest = pIpForwardTable->table[i].dwForwardDest; DWORD dwForwardMask = pIpForwardTable->table[i].dwForwardMask; DWORD dwForwardNextHop = pIpForwardTable->table[i].dwForwardNextHop; // 将0.0.0.0这条默认路由过滤掉 if ( 0 == dwForwardMask ) { continue; } // 判断目标IP地址与路由条目中的IP和子网掩码是否在同一子网中 // 在一个子网中,则使用该路由条目 if ( ( dwForwardDest & dwForwardMask ) == ( dwDestIp & dwForwardMask ) ) { dwDefaultGate = dwForwardNextHop; free(pIpForwardTable); return TRUE; } } free(pIpForwardTable); return FALSE; }对于人为添加的策略路由,也大概是通过上述代码的方法找到对应的策略路由的。
获取网卡上的IP、网关及DNS信息,获取最佳路由,遍历路由表中的条目(附源码)由讯客互联软件开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“获取网卡上的IP、网关及DNS信息,获取最佳路由,遍历路由表中的条目(附源码)”