Linux下C语言操作网卡的几个代码实例!特别实用
来源:良许Linux教程网
时间:2025-01-14 13:09:37 345浏览 收藏
怎么入门文章编程?需要学习哪些知识点?这是新手们刚接触编程时常见的问题;下面golang学习网就来给大家整理分享一些知识点,希望能够给初学者一些帮助。本篇文章就来介绍《Linux下C语言操作网卡的几个代码实例!特别实用》,涉及到,有需要的可以收藏一下
下面是对原文的重新表述,重点在于如何用C语言直接操作网络接口,例如读写IP地址和MAC地址。
如何使用C语言直接操作网络接口?
在这篇文章中,我们将讨论如何在C语言中直接操作网络接口。这包括读取和修改IP地址、MAC地址等信息。
1. 基本原理
我们可以通过使用系统提供的socket()
和ioctl()
函数来实现这些操作。这些函数允许我们与网络接口进行直接的交互,从而获取和设置与网络有关的各种参数。
你可以通过使用这些C语言函数来控制和管理当前系统上的网络接口。通过这两种系统调用,我们可以轻松实现网络接口的操作和管理。
int socket(int domain, int type, int protocol); 功能: 创建套接字 参数: domain: Name Purpose Man page AF_UNIX, AF_LOCAL Local communication unix(7) AF_INET IPv4 Internet protocols ip(7) type: SOCK_STREAM Provides sequenced, reliable, two-way, connection-based byte streams. An out-of-band data transmission mecha‐ nism may be supported. SOCK_DGRAM Supports datagrams (connectionless, unreliable messages of a fixed maximum length). protocol: 通常为0 返回值: 成功:新的套接字的文件描述符 失败:错误码,负值 int ioctl(int fd, unsigned long request, ...); 参数: fd :文件描述符 request:命令 ... :参数
其中网络用到的request定义头文件位于:
/usr/include/linux/sockios.h /* Linux-specific socket ioctls */ #define SIOCINQ FIONREAD #define SIOCOUTQ TIOCOUTQ /* output queue size (not sent + not acked) */ /* Routing table calls. */ #define SIOCADDRT 0x890B /* add routing table entry */ #define SIOCDELRT 0x890C /* delete routing table entry */ #define SIOCRTMSG 0x890D /* call to routing system */ /* Socket configuration controls. */ #define SIOCGIFNAME 0x8910 /* get iface name */ #define SIOCSIFLINK 0x8911 /* set iface channel */ #define SIOCGIFCONF 0x8912 /* get iface list */ #define SIOCGIFFLAGS 0x8913 /* get flags */ #define SIOCSIFFLAGS 0x8914 /* set flags */ #define SIOCGIFADDR 0x8915 /* get PA address */ #define SIOCSIFADDR 0x8916 /* set PA address */ #define SIOCGIFDSTADDR 0x8917 /* get remote PA address */ #define SIOCSIFDSTADDR 0x8918 /* set remote PA address */ #define SIOCGIFBRDADDR 0x8919 /* get broadcast PA address */ #define SIOCSIFBRDADDR 0x891a /* set broadcast PA address */ #define SIOCGIFNETMASK 0x891b /* get network PA mask */ #define SIOCSIFNETMASK 0x891c /* set network PA mask */ #define SIOCGIFMETRIC 0x891d /* get metric */ #define SIOCSIFMETRIC 0x891e /* set metric */ #define SIOCGIFMEM 0x891f /* get memory address (BSD) */ #define SIOCSIFMEM 0x8920 /* set memory address (BSD) */ #define SIOCGIFMTU 0x8921 /* get MTU size */ #define SIOCSIFMTU 0x8922 /* set MTU size */ #define SIOCSIFNAME 0x8923 /* set interface name */ #define SIOCSIFHWADDR 0x8924 /* set hardware address */ #define SIOCGIFENCAP 0x8925 /* get/set encapsulations */ #define SIOCSIFENCAP 0x8926 #define SIOCGIFHWADDR 0x8927 /* Get hardware address */ #define SIOCGIFSLAVE 0x8929 /* Driver slaving support */ #define SIOCSIFSLAVE 0x8930 #define SIOCADDMULTI 0x8931 /* Multicast address lists */ #define SIOCDELMULTI 0x8932 #define SIOCGIFINDEX 0x8933 /* name -> if_index mapping */ #define SIOGIFINDEX SIOCGIFINDEX /* misprint compatibility :-) */ #define SIOCSIFPFLAGS 0x8934 /* set/get extended flags set */ #define SIOCGIFPFLAGS 0x8935 #define SIOCDIFADDR 0x8936 /* delete PA address */ #define SIOCSIFHWBROADCAST 0x8937 /* set hardware broadcast addr */ #define SIOCGIFCOUNT 0x8938 /* get number of devices */ ……
其中ioctl的参数需要借助结构体struct ifreq
, 定义头文件:
/usr/include/linux/if.h #if __UAPI_DEF_IF_IFREQ struct ifreq { #define IFHWADDRLEN 6 union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ } ifr_ifrn; union { struct sockaddr ifru_addr; struct sockaddr ifru_dstaddr; struct sockaddr ifru_broadaddr; struct sockaddr ifru_netmask; struct sockaddr ifru_hwaddr; short ifru_flags; int ifru_ivalue; int ifru_mtu; struct ifmap ifru_map; char ifru_slave[IFNAMSIZ]; /* Just fits the size */ char ifru_newname[IFNAMSIZ]; void * ifru_data; struct if_settings ifru_settings; } ifr_ifru; }; #endif /* __UAPI_DEF_IF_IFREQ */ #define ifr_name ifr_ifrn.ifrn_name /* interface name */ #define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ #define ifr_addr ifr_ifru.ifru_addr /* address */ #define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ #define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ #define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ #define ifr_flags ifr_ifru.ifru_flags /* flags */ #define ifr_metric ifr_ifru.ifru_ivalue /* metric */ #define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ #define ifr_map ifr_ifru.ifru_map /* device map */ #define ifr_slave ifr_ifru.ifru_slave /* slave device */ #define ifr_data ifr_ifru.ifru_data /* for use by interface */ #define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */ #define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */ #define ifr_qlen ifr_ifru.ifru_ivalue /* Queue length */ #define ifr_newname ifr_ifru.ifru_newname /* New name */ #define ifr_settings ifr_ifru.ifru_settings /* Device/proto settings*/
二、函数实现
下面将实现不同功能的函数一一列举。
1. 获取本机网卡IP
int getLocalIp(const char *eth, char *ip) { struct ifreq ifr; struct sockaddr_in sin; int fd; bzero(&ifr, sizeof(ifr)); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1; } strcpy(ifr.ifr_name, eth); if (ioctl(fd, SIOCGIFADDR, &ifr) return -1; } memcpy(&sin, &ifr.ifr_addr, sizeof(sin)); snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr)); close(fd); return 0; }
2. 设置本网卡IP地址
int setIpAddrManual(const char *eth, char *ipstr) { int fd; struct sockaddr_in sin; struct ifreq ifr; bzero(&ifr, sizeof(ifr)); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1; } strcpy(ifr.ifr_name, eth); sin.sin_addr.s_addr = inet_addr(ipstr); sin.sin_family = AF_INET; memcpy(&ifr.ifr_addr, &sin, sizeof(sin)); if (ioctl(fd, SIOCSIFADDR, &ifr) ""); close(fd); return -1; } close(fd); return 0; }
3. 获取本机网卡Mac地址
int getLocalMac(const char *eth, char *mac) { int fd; struct ifreq ifr; bzero(&ifr, sizeof(ifr)); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1; } strcpy(ifr.ifr_name, eth); if (ioctl(fd, SIOCGIFHWADDR, &ifr) return -1; } snprintf(mac,18, "%02x:%02x:%02x:%02x:%02x:%02x", (unsigned char) ifr.ifr_hwaddr.sa_data[0], (unsigned char) ifr.ifr_hwaddr.sa_data[1], (unsigned char) ifr.ifr_hwaddr.sa_data[2], (unsigned char) ifr.ifr_hwaddr.sa_data[3], (unsigned char) ifr.ifr_hwaddr.sa_data[4], (unsigned char) ifr.ifr_hwaddr.sa_data[5]); close(fd); return 0; }
4. 设置网卡mac地址
/* support format [00:11:22:33:44:55] */ #define MAC_ARRAY(mac_array) (unsigned int *)&mac_array[0],(unsigned int *)&mac_array[1],(unsigned int *)&mac_array[2],(unsigned int *)&mac_array[3],(unsigned int *)&mac_array[4],(unsigned int *)&mac_array[5] int setLocalMac(const char *eth, char *mac) { int fd; struct ifreq ifr; unsigned char mac_array[6] = {0}; bzero(&ifr, sizeof(ifr)); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1; } strcpy(ifr.ifr_name, eth); ifr.ifr_hwaddr.sa_family = AF_LOCAL; sscanf(mac,"%02x:%02x:%02x:%02x:%02x:%02x", MAC_ARRAY(mac_array)); memcpy(ifr.ifr_hwaddr.sa_data,mac_array,6); if (ioctl(fd, SIOCSIFHWADDR, &ifr) "SIOCSIFHWADDR:"); close(fd); return -1; } close(fd); return 0; }
注意:
- 网卡地址的第一字节必须是偶数
- sa_family 值必须为:AF_LOCAL
5. 获取网卡mtu
int getMtu(const char *eth, char *mtu) { int fd; struct ifreq ifr; bzero(&ifr, sizeof(ifr)); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1; } strcpy(ifr.ifr_name, eth); if (ioctl(fd, SIOCGIFMTU, &ifr) return -1; } snprintf(mtu,64, "%d", (unsigned char) ifr.ifr_mtu); close(fd); return 0; }
6. 获取广播地址
int getBroadAddr(const char *eth, char *ip) { int fd; struct sockaddr_in sin; struct ifreq ifr; bzero(&ifr, sizeof(ifr)); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1; } strcpy(ifr.ifr_name, eth); if (ioctl(fd, SIOCGIFBRDADDR, &ifr) ""); close(fd); return -1; } memcpy(&sin, &ifr.ifr_broadaddr, sizeof(sin)); snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr)); close(fd); return 0; }
7. 获取掩码
int getNetMask(const char *eth, char *mask) { int fd; struct sockaddr_in sin; struct ifreq ifr; bzero(&ifr, sizeof(ifr)); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1; } strcpy(ifr.ifr_name, eth); if (ioctl(fd, SIOCGIFNETMASK, &ifr) ""); close(fd); return -1; } memcpy(&sin, &ifr.ifr_netmask, sizeof(sin)); snprintf(mask, IP_SIZE, "%s", inet_ntoa(sin.sin_addr)); close(fd); return 0; }
8. 获取网卡flag
int getFlags(const char *eth, char *fg) { int fd; struct sockaddr_in sin; struct ifreq ifr; bzero(&ifr, sizeof(ifr)); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1; } strcpy(ifr.ifr_name, eth); if (ioctl(fd, SIOCGIFFLAGS, &ifr) ""); close(fd); return -1; } snprintf(fg, IP_SIZE, "%x", ifr.ifr_flags); close(fd); return 0; }
三、测试
1. 测试程序
int main(int argc, char **argv) { int fg=0; char mac[32]={}; char ip[IP_SIZE]={0}; char buf[64]; getBroadAddr(ethname,ip); printf("broad ip:\t%s\n",ip); getNetMask(ethname,ip); printf("mask:\t%s\n",ip); setIpAddrManual(ethname, "1.1.1.1"); getLocalIp(ethname,ip); printf("ip:\t%s\n",ip); setLocalMac(ethname,"00:11:22:33:44:55"); getLocalMac(ethname,mac); printf("mac:\t%s\n",mac); getMtu(ethname,buf); printf("mtu:\t%s\n",buf); return 1; }
2. 执行结果
执行后结果:
peng@ubuntu:~/work/test/ip$ ifconfig eth0 Link encap:Ethernet HWaddr 00:11:22:33:44:55 inet addr:1.1.1.1 Bcast:1.255.255.255 Mask:255.0.0.0 inet6 addr: fe80::d9d4:d42b:a04a:9d40/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:188577 errors:0 dropped:0 overruns:0 frame:0 TX packets:208116 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:53762370 (53.7 MB) TX bytes:172094089 (172.0 MB)
完整代码,后天回复:eth
到这里,我们也就讲完了《Linux下C语言操作网卡的几个代码实例!特别实用》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于Linux,Linux系统,Shell脚本,Linux命令,linux入门,linux教程,linux学习,嵌入式Linux的知识点!
声明:本文转载于:良许Linux教程网 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
500 收藏
最新阅读
更多>
-
322 收藏
-
125 收藏
-
433 收藏
-
159 收藏
-
226 收藏
-
158 收藏
课程推荐
更多>
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习