获取网卡上的IP、网关及DNS信息,获取最佳路由,遍历路由表中的条目(附源码)
VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)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;
}
对于人为添加的策略路由,也大概是通过上述代码的方法找到对应的策略路由的。
相关文章:

获取网卡上的IP、网关及DNS信息,获取最佳路由,遍历路由表中的条目(附源码)
VC常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...&a…...

保姆级 -- Zookeeper超详解
1. Zookeeper 是什么(了解) Zookeeper 是一个 分布式协调服务 的开源框架, 主要用来解决分布式集群中应用系统的一致性问题, 例如怎样避免同时操作同一数据造成脏读的问题. ZooKeeper 本质上是 一个分布式的小文件存储系统 . 提供基于类似于文件系统的目录树方式的数据存储, …...

【通意千问】大模型GitHub开源工程学习笔记(2)--使用Qwen进行推理的示例代码解析,及transformers的库使用
使用Transformers来使用模型 如希望使用Qwen-chat进行推理,所需要写的只是如下所示的数行代码。请确保你使用的是最新代码,并指定正确的模型名称和路径,如Qwen/Qwen-7B-Chat和Qwen/Qwen-14B-Chat 这里给出了一段代码 from transformers import AutoModelForCausalLM, Aut…...
从0开始python学习-23.selenium 常见鼠标的操作
注意:必须创建一个事件链对象(ActionChains);最后鼠标事件链完成之后一定要进行事务提交perform()(如果事件链不提交那么所有的鼠标事件都不会执行) 1. 左键单击:click()…...

电气基础——电源、变压器、接触器、断路器、线缆
目录 1.电源 2.变压器 三项电和2相电的转换 3.接触器 4.断路器 5.线缆 1.电源 2.变压器 三项电和2相电的转换 三相电转为2相电 1.变压器 2.相位移转换器 3.电容器 两相电变不了三相电。但是两相电可以通过电容移相后带动三相电机 零线,地线Nÿ…...

步力宝科技爆款产品定位,开创智能物联网新商业
数据显示,中国处于 “亚健康”状态人口数量约占总人口的70%,亚健康是一种临界状态,指介于健康和疾病之间的状态。亚健康是一个动态演变的过程,既有向慢病发展的趋势,也能通过合理的干预使人体重返健康状态,…...

凉鞋的 Unity 笔记 105. 第一个通识:编辑-测试 循环
105. 第一个通识:编辑-测试 循环 在这一篇,我们简单聊聊此教程中所涉及的一个非常重要的概念:循环。 我们在做任何事情都离不开某种循环,比如每天的 24 小时循环,一日三餐循环,清醒-睡觉循环。 在学习一…...

Bug:elementUI样式不起作用、Vue引入组件报错not found等(Vue+ElementUI问题汇总)
前端问题合集:VueElementUI 1. Vue引用Element-UI时,组件无效果解决方案 前提: 已经安装好elementUI依赖 //安装依赖 npm install element-ui //main.js中导入依赖并在全局中使用 import ElementUI from element-ui Vue.use(ElementUI)如果此…...
【大麦小米学量化】使用文心一言AI编写股票量化交易策略代码(含演示代码和进阶演示)
文章目录 AI是个宝前言一、文心一言是什么?二、让AI根据策略写出代码1. 策略提示词2. AI给出的策略代码及说明 三、进阶调试总结 AI是个宝 小米听说百度开放了文心一言AI,好奇的跑去问大麦:“文心一言都放开了,什么代码都可以写&a…...
软考 系统架构设计师系列知识点之软件架构风格(1)
这个十一注定是一个不能放松、保持“紧”的十一。由于报名了全国计算机技术与软件专业技术资格(水平)考试,11月4号就要考试,因此8天长假绝不能荒废,必须要好好利用起来。现在将各个核心知识点一一进行提炼并做记录。 所…...

轮询与中断
中断控制器 #include"exynos_4412.h"int main() {/*产生一个中断信号*//*1.属于外设层次,让外部的硬件控制器能产生一个中断信号并发送给中断控制器*//*将GPX1_1设置成中断功能*/GPX1.CON GPX1.CON |( 0xF << 4);/*设置GPX1_1中断的触发方式---下降…...

使用docker完成minio服务部署扩容备份迁移生产实践文档
一、minio服务扩容方案 当服务器存储空间不足的时候,需要进行扩容,扩容过程中需要短暂停机时间,预计在一小时内能够完成和恢复 统一注意事项 强烈建议为部署中的所有节点选择基本相似的硬件配置。确保硬件(CPU、内存、主板、存…...

管道-有名管道
一、有名管道 有名管道与匿名管道的不同: 有名管道提供了一个路径名,并以FIFO的文件形式存在于文件系统中。与匿名管道不同,有名管道可以被不相关的进程使用,只要它们可以访问该路径,就能够通过有名管道进行通信。 FI…...

谷歌注册手机号码无法验证
1. 打开设置,在语言中点击添加语言搜索English并添加 2. 点击添加后把首选语言换成英语 3. 然后重启浏览器,这时候浏览器就是英文了,最后打开注册页面就能接收短信了...

C语言编译与链接过程详解
C语言编译与链接过程详解 源文件 main.c #include <stdio.h>extern int data; extern int add(int a,int b);int a1; int a2 0; int a3 10;static int b1; static int b2 0; static int b3 20;int main() {int c1;int c2 0;int c3 30;static int d1;static int …...
Qt信号和槽 定时器
文章目录 1 信号和槽1.1 信号和槽的概念1.2 信号和槽的应用1.3 信号和槽的连接1.4 信号和槽的特性1.5 生活中的类似例子1.6 信号和槽的优势 2 信号和槽的使用2.1 控件的信号和槽2.2 自定义信号和槽2.3 信号和槽的参数传递 3 定时器3.1 QTimer类的基本使用3.2 QTimer类的成员函数…...

zemax对称式目镜
两个几乎对称的双胶合透镜相对放置,可以达到25度的半视场 为了加工方便,这两个透镜组采用相同的结构 对称式目镜要求各组透镜自行校正色差,这样倍率色差也随之而校正。 它还能校正两种像差,慧差和象散。 对称目镜的结构更紧&…...

层次架构、面向服务架构(四十四)
层次架构设计 表现层、中间层、数据访问层、数据架构规划、物联网层次架构、层次式架构案例分析。 层次结构缺点就是效率问题,上一层调用下一层。 1、着重写中间层 组件设计:面向接口编程,分为接口和实现类。 实体设计:实体表…...
Ubuntu22无法自动进入lightdm图像界面
问题:Ubuntu22无法自动进入lightdm图像界面,必须手动运行 lightdm start解决方案: 方案一: 运行一个终端输入 cat /etc/X11/default-display-manager /etc/init/lightdm.conf不接受lightdm作为设置,但是,/…...
01BFS最短距离的原理和C++实现
时间复杂度 O(n),n是边数。 使用前提 边的权只有两种:0,1。 典型场景 n个端点的无向图,编号范围[0,n)。Edges0表示{{n1,n2},...{n3,n4}}表示n1和n2,n3和n4之间有路联接。Edges1表示{{n1,n2},...{n3,n4}}表示n1和n2,n3和n4之间…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...