石佛营网站建设,公众号平台app,安卓软件app,网易云音乐网站开发介绍VC常用功能开发汇总#xff08;专栏文章列表#xff0c;欢迎订阅#xff0c;持续更新...#xff09;https://blog.csdn.net/chenlycly/article/details/124272585C软件异常排查从入门到精通系列教程#xff08;专栏文章列表#xff0c;欢迎订阅#xff0c;持续更新...常用功能开发汇总专栏文章列表欢迎订阅持续更新...https://blog.csdn.net/chenlycly/article/details/124272585C软件异常排查从入门到精通系列教程专栏文章列表欢迎订阅持续更新...https://blog.csdn.net/chenlycly/article/details/125529931C软件分析工具从入门到精通案例集锦专栏文章正在更新中...https://blog.csdn.net/chenlycly/article/details/131405795C/C基础与进阶专栏文章持续更新中...https://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;
}
对于人为添加的策略路由也大概是通过上述代码的方法找到对应的策略路由的。