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

Linux实用功能代码集(1) —— 获得机器IP和MAC

不管是在PC(如Ubuntu)还是嵌入式设备(嵌入式Linux)上经常需要获取本机IP和MAC。下边就给出实现此功能的代码,并进行一定讲解。

代码如下:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <net/if.h> #include <arpa/inet.h> int get_ip_by_ifname(const char *ifname, char *ip_buf, int buf_len) { int sockfd = -1; struct ifreq ifr; struct sockaddr_in *sin; if (!ifname || !ip_buf) { printf("parameter can't be null\n"); return -1; } sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket failed"); return -1; } strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) { perror("ioctl SIOCGIFADDR failed"); close(sockfd); return -1; } sin = (struct sockaddr_in *)&ifr.ifr_addr; strncpy(ip_buf, inet_ntoa(sin->sin_addr), buf_len - 1); close(sockfd); return 0; } int get_mac_by_ifname(const char *ifname, char *mac_buf, int buf_len) { int sockfd = -1; struct ifreq ifr; unsigned char *mac = NULL; if (!ifname || !mac_buf) { printf("parameter can't be null\n"); return -1; } sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket failed"); return -1; } strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) { perror("ioctl SIOCGIFHWADDR failed"); close(sockfd); return -1; } mac = (unsigned char *)ifr.ifr_hwaddr.sa_data; snprintf(mac_buf, buf_len, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); close(sockfd); return 0; } int main(int argc, char *argv[]) { int ret; //ip char ip_addr[32] = {0}; //ret = get_ip_by_ifname("eth0", ip_addr, sizeof(ip_addr)); ret = get_ip_by_ifname("ens33", ip_addr, sizeof(ip_addr)); if (!ret) printf("ip is: %s\n", ip_addr); //mac char mac_addr[32] = {0}; //ret = get_mac_by_ifname("eth0", mac_addr, sizeof(mac_addr)); ret = get_mac_by_ifname("ens33", mac_addr, sizeof(mac_addr)); if (!ret) printf("mac is: %s\n", mac_addr); return 0; }

main函数中分为了两部分:获取IP地址,这通过get_ip_by_ifname函数实现;获取MAC地址,这通过get_mac_by_if_name函数实现。

下边依次对这两个函数进行讲解。

  • get_ip_by_ifname函数

get_ip_by_name函数主要步骤如下:

1)创建socket

代码片段如下:

sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket failed"); return -1; }

此步骤的功能是创建一个IPv4的UDP套接字。

2)获取IP地址并赋值给函数参数

代码片段如下:

strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) { perror("ioctl SIOCGIFADDR failed"); close(sockfd); return -1; } sin = (struct sockaddr_in *)&ifr.ifr_addr; strncpy(ip_buf, inet_ntoa(sin->sin_addr), buf_len - 1);

通过SIOCGIFADDR这一ioctl告诉内核,需要获取IP。通过ifr.ifr_name指明需要获取哪个网卡的IP地址。ioctl调用后,内核会把IP地址写入ifr.ifr_addr。

将获得的IP地址通过strncpy函数拷贝给函数参数ip_buf。

3)关闭socket

代码片段如下:

close(sockfd);
  • get_mac_by_ifname函数

其实get_mac_by_ifname函数和get_ip_by_ifname函数流程基本一致。只是第2步不同。

2)获取MAC地址并赋值给函数参数

代码片段如下:

strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) { perror("ioctl SIOCGIFHWADDR failed"); close(sockfd); return -1; } mac = (unsigned char *)ifr.ifr_hwaddr.sa_data; snprintf(mac_buf, buf_len, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

通过SIOCGIFHWADDR这一ioctl告诉内核,需要获取MAC。通过ifr.ifr_name指明需要获取哪个网卡的MAC地址。ioctl调用后,内核会把IP地址写入ifr.ifr_hwaddr中。

将获得的MAC地址通过sprintf函数赋值给函数参数mac_buf。

注:

1)get_mac_by_ifname和get_ip_by_ifname中的代码完全可以合在一起,无需创建两个socket。笔者这样写是为了功能独立以及便于理解。

2)对于Ubuntu来说,网卡名称一般为"ens33";对于嵌入式Linux来说,则仍一般是传统的"eth0"。

这里也给出相关的ioctl:

  • ioctl(sockfd, SIOCGIFADDR, &ifr); // 获取IP
  • ioctl(sockfd, SIOCGIFHWADDR, &ifr);// 获取MAC
  • ioctl(sockfd, SIOCGIFNETMASK, &ifr); // 获取子网掩码
  • ioctl(sockfd, SIOCGIFBRDADDR, &ifr); // 获取广播地址

对以上代码进行编译,实际命令及结果如下(笔者的环境为VMWare虚拟机,Ubuntu20.04):

$ gcc get_ip_mac.c -o get_ip_mac $

实际执行结果为:

$ ./get_ip_mac ip is: 192.168.163.128 mac is: 00:0c:29:23:93:a0

与执行ifconfig ens33命令结果一致:

$ ifconfig ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.163.128 netmask 255.255.255.0 broadcast 192.168.163.255 inet6 fe80::dbbe:2936:42b0:1c73 prefixlen 64 scopeid 0x20<link> ether 00:0c:29:23:93:a0 txqueuelen 1000 (Ethernet) RX packets 182822 bytes 145203754 (145.2 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 114094 bytes 42758976 (42.7 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 20166 bytes 2886087 (2.8 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 20166 bytes 2886087 (2.8 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
$ ifconfig ens33 ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.163.128 netmask 255.255.255.0 broadcast 192.168.163.255 inet6 fe80::dbbe:2936:42b0:1c73 prefixlen 64 scopeid 0x20<link> ether 00:0c:29:23:93:a0 txqueuelen 1000 (Ethernet) RX packets 182824 bytes 145203893 (145.2 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 114097 bytes 42759194 (42.7 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

完整工程代码已上传至:Linux下获取IP和MAC的实用代码资源-CSDN下载。

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

相关文章:

  • 2026年口碑好的家用插线板品牌推荐:工业插线板/大功率插线板/智能USB插线板公司口碑推荐 - 品牌宣传支持者
  • Fish Speech 1.5参数详解与调优:Temperature/Top-P/重复惩罚实战设置
  • 嵌入式极简日志模块:零依赖、带时间戳与颜色的轻量级调试方案
  • 2026年质量好的薄膜压力传感器品牌推荐:手指可弯曲压力传感器优质供应商推荐 - 品牌宣传支持者
  • 2026年靠谱的淬火炉公司推荐:网带式淬火炉/辊底式盐浴淬火炉/网带式盐浴淬火炉公司选择指南 - 品牌宣传支持者
  • OpenClaw开发助手配置:Qwen3-32B辅助日志分析与代码调试
  • 2026年口碑好的广东会议活动策划公司推荐:广东庆典活动策划回购率高推荐 - 品牌宣传支持者
  • MAX31855热电偶驱动开发实战:SPI接口与冷端补偿详解
  • 5分钟搞定RT-Thread的DMA串口配置:GD32F450硬件加速指南
  • 2026年评价高的汽车托运品牌推荐:自驾游汽车托运/新疆自驾游汽车托运/乌鲁木齐二手车汽车托运公司口碑推荐 - 品牌宣传支持者
  • STM32一键下载电路原理与CH340时序控制设计
  • Qwen3-TTS-VoiceDesign语音设计入门必看:3步用中文描述生成萝莉/少年/温柔等风格人声
  • Qwen3-TTS部署案例:数字人直播中实时语音驱动唇形同步技术实现
  • Harmonyos应用实例150:分式方程增根侦探
  • 2026年知名的织物传感器公司推荐:电动车压力传感器/电阻式压敏传感器/离床报警压力传感器销售厂家推荐 - 品牌宣传支持者
  • 5个维度教你打造个人音乐库:网易云音乐下载器一站式解决方案
  • 2026年比较好的展台搭建品牌推荐:北京展台搭建优质公司推荐 - 品牌宣传支持者
  • Unity3D书页卷曲效果插件:从零到一的完整实现指南
  • 终极指南:如何让KlipperScreen成为您的3D打印控制中心
  • PowerToys Everything插件:重新定义Windows文件检索效率的革命性工具
  • RVC模型多说话人混合效果展示:创造全新的合成音色
  • Qwen3-Reranker-0.6B性能优化:GPU加速与显存管理技巧
  • ROS图像处理避坑指南:cv_bridge转换、话题延迟与虚拟摄像头测试全解析
  • 青少年健康坐姿与环境监测嵌入式系统设计
  • Gemma-3-12b-it显存监控教程:实时查看GPU内存分配与释放过程
  • 基于StructBERT的智能客服问答匹配:JavaScript前端交互实现
  • NEURAL MASK开源大模型教程:Python API调用+自定义后处理代码实例
  • Arduino控制DYNAMIXEL舵机的协议栈实现与硬件适配
  • 从CV到TDE:Tessy单元测试的完整结果分析手册(以I2C驱动测试为例)
  • Nanbeige 4.1-3B像素冒险聊天终端:JRPG风AI对话实战教程