当前位置: 首页 > news >正文

网络配置工具类详解

CNet 网络配置工具类详解

平台:仅支持Linux,大量使用ioctl系统调用


一、概述

CNet是一个纯静态方法的网络配置工具类,封装了 Linux 下常用的网络操作:

功能类别涵盖内容
IP 地址读取/设置本机 IP、子网掩码
网关读取/添加/删除/设置默认网关
DNS读取/写入/etc/resolv.conf
MAC 地址读取本机 MAC、生成随机 MAC
网卡状态网线插入检测、网卡使能/禁用、接口是否存在
路由 metric设置网卡路由优先级
Socket 绑定将套接字绑定到指定网卡

全部方法都是static,无需实例化即可调用。


二、头文件与依赖

extern"C"{#include<stdio.h>#include<string.h>#include<arpa/inet.h>// inet_ntoa(), inet_addr()#include<sys/ioctl.h>// ioctl 系统调用#include<net/if.h>// ifreq, IFNAMSIZ#include<unistd.h>#include<linux/if.h>#include<linux/ethtool.h>// ETHTOOL_GLINK 网线检测#include<linux/rtnetlink.h>// 路由#include<net/route.h>// rtentry 路由结构#include<sys/time.h>#include<dirent.h>};

核心武器是ioctl——Linux 下操作网络接口的全能接口。


三、IP 地址操作

3.1 整数 ↔ 字符串互转

// 整数 IP(网络字节序) → 字符串 "192.168.1.100"char*IpU32ToStr(uint32_tu32_ip);// 字符串 IP → 整数(网络字节序)unsignedintIpStrToU32(constchar*sz_ip);

内部其实就两层皮:

// IpU32ToStr 内部:returninet_ntoa(*(structin_addr*)&u32_ip);// IpStrToU32 内部:returninet_addr(sz_ip);

⚠️inet_addr()在 IP 为0时返回INADDR_NONE,但代码未做校验,实际使用有坑。

3.2 读取本机 IP

boolGetLocalIp(constchar*interface_name,char*sz_ip,uint32_t&u32_ip);

实现套路(后文类似方法都这个套路):

intsock_fd=socket(AF_INET,SOCK_DGRAM,0);// 创建套接字strncpy(stIfreq.ifr_name,interface_name,IFNAME_SIZE);ioctl(sock_fd,SIOCGIFADDR,&stIfreq);// 发给内核问 IP// 取出结果,转换,关闭套接字

SIOCGIFADDR= Socket I/O Control 获取接口地址。

3.3 设置本机 IP

boolSetLocalIp(constchar*interface_name,constchar*sz_ip);boolSetLocalIp(constchar*interface_name,uint32_tu32_ip);
sock=socket(AF_INET,SOCK_DGRAM,0);// 注意是 DGRAM,不是 STREAMstrncpy(ifr.ifr_name,interface_name,IFNAMSIZ);si.sin_family=PF_INET;si.sin_addr.s_addr=u32_ip;memcpy(&ifr.ifr_addr,&si,sizeof(structsockaddr_in));ioctl(sock,SIOCSIFADDR,&ifr);// SIOCS = Set

SIOCSIFADDR= Socket I/O Control Set Interface Address。

3.4 子网掩码读取/设置

boolGetNetMask(constchar*interface_name,char*sz_mask);boolGetNetMask(constchar*interface_name,uint32_t&mask);boolSetNetMask(constchar*interface_name,constchar*sz_mask);boolSetNetMask(constchar*interface_name,uint32_tmask);

底层用SIOCGIFNETMASK/SIOCSIFNETMASKioctl。


四、网关(路由)操作

这是最复杂的部分,涉及/proc/net/route文件解析。

4.1 核心数据结构

structroute_info{u_int dstAddr;u_int srcAddr;u_int gateWay;charifName[IF_NAMESIZE];};

4.2 读取网关

boolGetLocalGateWay(constchar*interface_name,char*sz_gw);boolGetLocalGateWay(constchar*interface_name,uint32_t&gw);

实现:打开/proc/net/route,逐行解析:

// /proc/net/route 格式示例:// Iface Destination Gateway Flags RefCnt Use Metric Mask ...// eth0 00000000 0A00020A 0003 ... ... 100 0000F0F8FILE*fp=fopen(PROCNET_ROUTE_PATH,"r");// "/proc/net/route"fgets(buff,130,fp);// 跳过表头while(fgets(buff,130,fp)!=NULL){sscanf(buf,"%15s\t%08lX\t%08lX\t%8X\t",iface,&dest,&gate,&iflags);if(!strcmp(iface,interface_name)){if(iflags&(RTF_UP|RTF_GATEWAY))==(RTF_UP|RTF_GATEWAY)){gw=gate;// gate 是 16 进制整数returntrue;}}}

4.3 设置网关(先清后加)

boolSetLocalGateWay(constchar*interface_name,constchar*sz_gw);boolSetLocalGateWay(constchar*interface_name,uint32_tgw);

流程:CleanGateWay()AddLocalGateWay()

boolSetLocalGateWay(constchar*interface_name,uint32_tgw){CleanGateWay(interface_name);// 先删所有旧路由returnAddLocalGateWay(interface_name,gw);// 再加新路由}

4.4 添加/删除网关

staticboolAddLocalGateWay(constchar*interface_name,uint32_tgw);staticboolDelLocalGateWay(constchar*interface_name,uint32_tgw);

底层通过SIOCADDRT(Add Route)和SIOCDELRT(Delete Route)ioctl 实现:

structrtentryrt;memset(&rt,0,sizeof(structrtentry));rt.rt_flags=(RTF_UP|RTF_GATEWAY);// 标识为网关路由rt.rt_dst.sa_family=PF_INET;rt.rt_genmask.sa_family=PF_INET;sa.sin_addr.s_addr=gw;memcpy(&rt.rt_gateway,&sa,sizeof(structsockaddr));intskfd=socket(AF_INET,SOCK_DGRAM,0);ioctl(skfd,SIOCADDRT,&rt);// 写入内核路由表close(skfd);

五、DNS 服务器操作

直接读写/etc/resolv.conf

boolSetDNSServerIP(constchar*first_dns,constchar*second_dns);boolGetDNSServerIP(char*first_dns,char*second_dns);

写操作:

FILE*fp=fopen(RESOLV_CONF,"w");// "/etc/resolv.conf"snprintf(buf,sizeof(buf)-1,"nameserver %s\n""nameserver %s\n",first_dns,second_dns);fwrite(buf,1,strlen(buf),fp);fflush(fp);fclose(fp);

读操作:用LastPos()找到每行nameserver后面的空格位置,提取 IP。


六、MAC 地址操作

6.1 读取本机 MAC

boolGetLocalMac(constchar*interface_name,char*sz_mac);

通过SIOCGIFHWADDRioctl 获取:

strncpy(ifreq.ifr_name,interface_name,...);ioctl(sockfd,SIOCGIFHWADDR,&ifreq);// 获取硬件地址memcpy(mac_data,ifreq.ifr_hwaddr.sa_data,6);MacNumToStr(mac_data,sz_mac);// 格式化成 "XX:XX:XX:XX:XX:XX"

6.2 随机 MAC 生成

boolGetRandomMacAddr(char*sz_mac);

生成 6 字节随机数,但会过滤掉全零多播地址

do{for(i=0;i<6;i++)mac[i]=rand()&0xFF;}while(!IsValidEtherAddr((char*)mac));// 校验通过为止

七、网卡状态检测

7.1 网线是否插入

boolIsCablePluggedIn(constchar*interface_name);

使用ethtool接口:

structethtool_valueeth_data;eth_data.cmd=ETHTOOL_GLINK;// 查询链路状态eth_data.data=0;ifr.ifr_data=(char*)&eth_data;ioctl(sock,SIOCETHTOOL,&ifr);// 发给 ethtool 驱动// eth_data.data > 0 表示网线插着

7.2 网卡是否启用

boolGetNetworkEnableStatus(constchar*interface_name,bool&enable);boolSetNetworkEnableStatus(constchar*interface_name,boolenable);

通过SIOCGIFFLAGS(Get)和SIOCSIFFLAGS(Set)操作ifr_flags

ioctl(sock,SIOCGIFFLAGS,&ifr);enable=(ifr.ifr_flags&IFF_UP)!=0;// IFF_UP 表示已启用// 设置禁用:ifr.ifr_flags&=~IFF_UP;ioctl(sock,SIOCSIFFLAGS,&ifr);// 设置启用:ifr.ifr_flags|=IFF_UP|IFF_RUNNING;

7.3 网卡接口是否存在

boolIsNetworkInterfaceExist(constchar*interface_name);boolGetAllNetworkInterface(std::vector<std::string>&interface_name);

遍历/sys/class/net目录:

DIR*dir=opendir("/sys/class/net");structdirent*entry;while((entry=readdir(dir))!=NULL){if(entry->d_type==DT_LNK&&!strcmp(entry->d_name,interface_name)){exist=true;}}closedir(dir);

八、Socket 绑定到网卡

boolSockBindInterface(constchar*interface_name,intsock_fd);

使用SOL_SOCKET/SO_BINDTODEVICE选项:

strncpy(interface.ifr_ifrn.ifrn_name,interface_name,...);setsockopt(sock_fd,SOL_SOCKET,SO_BINDTODEVICE,(char*)&interface_name,sizeof(interface));

这样该 socket 收发的数据包都走指定网卡。


九、路由优先级(Metric)

boolSetRouteMetric(constchar*interface_name,uint32_tmetric);
ifr.ifr_metric=metric;// 0-255,值越大优先级越低ioctl(sockfd,SIOCSIFMETRIC,&ifr);

十、总结

技术亮点说明
ioctl系统调用贯穿整个模块,操作网络接口的金钥匙
/proc/net/route读取内核路由表,手动解析文本
/etc/resolv.conf直接读写 DNS 配置
/sys/class/net遍历网卡接口
ethtoolioctl查询网线物理连接状态
路由表操作SIOCADDRT/SIOCDELRT动态增删路由

整体是一个贴近 Linux 底层实现的网络配置工具,设计思路务实,不依赖第三方库,适合嵌入式 Linux 场景。

http://www.jsqmd.com/news/886535/

相关文章:

  • 毕业设计:基于mvc的高校办公室行政事务管理系统设计与实现(源码)
  • 集成学习在房价预测中的应用:从原理到实战调优
  • 告别手动搬运:这款抖音批量下载工具让内容收集效率翻倍
  • 第三卷第4章:原型模式设计思想
  • 【Unity编辑器拓展】实现ScriptableObject的结构体结构中,枚举变量显示中文描述
  • Unity中稳定低开销3D描边实现方案
  • Web渗透测试能力成长地图:从工具使用到漏洞认知跃迁
  • 基于GPS与RTC的高精度时钟设计:从触摸屏GUI到MOSFET驱动的嵌入式实践
  • Unity UI交互进阶:手把手教你打造一个支持单击、双击、长按的万能按钮组件
  • 告别抓瞎!手把手教你用Postman搞定微信小程序接口测试(附环境变量与断言实战)
  • UE5 RPG实战:用Motion Warping插件搞定角色释放技能时的自动转向(附蓝图接口优化)
  • 举一个具体例子说明为什么索引不是越多越好,举具体字段
  • 原子化半格:从数据中“生长”出可解释规则与泛化模型
  • MCBx51评估板:8051单片机开发全兼容方案解析
  • 毕业设计:基于java的在线问卷调查系统的设计与实现(源码)
  • Linux服务器被黑排查指南:进程、文件、日志、网络四维证据链
  • 2027考研全套资料免费分享
  • 从‘Hello World’到数据迁移:KingbaseES类型转换的5个高频实战场景解析
  • 哔哩漫游X:解锁B站全功能体验的终极指南
  • 阿波罗登月,不可能:读心术与影子叙事 ——不是向全世界展示登月,而是向全世界注射登月
  • OBS多平台直播革命:obs-multi-rtmp插件让你一次推流,全网覆盖
  • 关联规则挖掘在Calabi-Yau流形Hodge数分析中的应用与复现
  • 深挖 okbiye 核心能力|AI 毕业论文写作新模式,高效攻克毕业创作难题
  • 基于ESP32与Modbus RTU的太阳能光伏数据采集系统实战
  • 抖音内容高效采集终极指南:3大核心策略解锁完整下载方案
  • 别再乱点屏幕了!用Monkey黑白名单精准测试你的Android App(附完整配置文件)
  • 从RD、CS到WK:一文讲透SAR主流成像算法的演进与选型实战
  • Unity图片优化实战:解决UI图片内存暴涨与比例失控
  • 百度文心一言开发者如何通过Taotoken低成本接入多模型API
  • 2026 年 AI 毕业论文工具横评:从降 AIGC 率到智能排版,10 款平台实测谁才是毕业季的 “救命稻草”