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

Unix/Linux 平台通过 IP 地址获取接口名的 C++ 实现

🌐 Unix/Linux 平台通过 IP 地址获取接口名的 C++ 实现

在这里插入图片描述


📌 函数声明
ppp::string UnixAfx::GetInterfaceName(const IPEndPoint& address) noexcept {
  • 功能:根据给定的 IP 端点(IPEndPoint)获取对应的网络接口名称(如 eth0)。
  • 返回值:成功返回接口名,失败返回空字符串。
  • 平台限制:Android 需 API ≥ 24(Android 7.0+)。

🔍 代码逐行解析(含中文注释)
#if (!defined(_ANDROID) || __ANDROID_API__ >= 24)

🔹 平台兼容性检查

  • 仅在非 Android 或 Android API ≥ 24 时编译以下代码。

    struct ifaddrs* ifa = NULL;if (getifaddrs(&ifa)) {return "";}

🔹 获取网络接口列表

  • getifaddrs 获取所有网络接口信息链表头 ifa
  • 失败时返回空字符串(如权限不足)。

    struct ifaddrs* oifa = ifa;  // 保存链表头用于后续释放内存while (NULL != ifa) {struct sockaddr* addr = ifa->ifa_addr;if (NULL != addr) {

🔹 遍历接口链表

  • oifa 备份链表头指针,确保后续能正确释放内存。
  • 跳过无地址信息的接口(ifa_addrNULL)。

            switch (addr->sa_family) {case AF_INET: {  // IPv4 地址if (address.GetAddressFamily() != AddressFamily::InterNetwork) {break;}

🔹 处理 IPv4 地址

  • 检查目标地址是否为 IPv4 类型(InterNetwork)。
  • 类型不匹配则跳过当前接口。

                    struct sockaddr_in* in4_addr = (struct sockaddr_in*)addr;if (in4_addr->sin_addr.s_addr != address.GetAddress()) {break;}

🔹 比较 IPv4 地址

  • 将接口地址转为 sockaddr_in 结构。
  • 对比接口的 IPv4 地址(s_addr)与目标地址是否一致。

                    freeifaddrs(oifa);  // 释放接口链表内存return ifa->ifa_name;  // 返回匹配的接口名}

🔹 匹配成功处理

  • 释放链表内存,返回当前接口名称(如 "eth0")。

                case AF_INET6: {  // IPv6 地址if (address.GetAddressFamily() != AddressFamily::InterNetworkV6) {break;}

🔹 处理 IPv6 地址

  • 检查目标地址是否为 IPv6 类型(InterNetworkV6)。

                    struct sockaddr_in6* in6_addr = (struct sockaddr_in6*)addr; {int length;Byte* address_bytes = address.GetAddressBytes(length);length = std::min<int>(sizeof(in6_addr->sin6_addr), length);if (memcmp(&in6_addr->sin6_addr, address_bytes, length) != 0) {break;}}

🔹 比较 IPv6 地址

  • 获取目标地址的字节数组(address_bytes)。
  • 使用 memcmp 比较接口的 IPv6 地址(128 位)是否一致。

                    freeifaddrs(oifa);return ifa->ifa_name;  // 返回匹配的接口名}};}ifa = ifa->ifa_next;  // 移动到下一个接口节点}

🔹 继续遍历

  • 若当前接口不匹配,移动到链表下一个节点。

    if (NULL != oifa) {freeifaddrs(oifa);  // 释放整个接口链表}
#endifreturn "";  // 未找到匹配接口
}

🔹 收尾处理

  • 遍历结束后释放接口链表内存。
  • 返回空字符串表示未找到匹配接口。

🧩 完整代码实现

ppp::string UnixAfx::GetInterfaceName(const IPEndPoint& address) noexcept {
#if (!defined(_ANDROID) || __ANDROID_API__ >= 24)struct ifaddrs* ifa = NULL;// 获取所有网络接口信息链表if (getifaddrs(&ifa)) {return ""; // 获取失败返回空}struct ifaddrs* oifa = ifa; // 备份链表头指针while (NULL != ifa) {struct sockaddr* addr = ifa->ifa_addr;if (NULL != addr) {switch (addr->sa_family) {case AF_INET: { // IPv4 处理分支// 检查地址族是否匹配if (address.GetAddressFamily() != AddressFamily::InterNetwork) {break;}struct sockaddr_in* in4_addr = (struct sockaddr_in*)addr;// 比较 IPv4 地址是否一致if (in4_addr->sin_addr.s_addr != address.GetAddress()) {break;}freeifaddrs(oifa); // 释放链表内存return ifa->ifa_name; // 返回接口名}case AF_INET6: { // IPv6 处理分支if (address.GetAddressFamily() != AddressFamily::InterNetworkV6) {break;}struct sockaddr_in6* in6_addr = (struct sockaddr_in6*)addr; {int length;// 获取目标地址的二进制形式Byte* address_bytes = address.GetAddressBytes(length);// 安全比较长度(IPv6 固定为 16 字节)length = std::min<int>(sizeof(in6_addr->sin6_addr), length);// 内存比较 IPv6 地址if (memcmp(&in6_addr->sin6_addr, address_bytes, length) != 0) {break;}}freeifaddrs(oifa);return ifa->ifa_name; // 返回接口名}};}ifa = ifa->ifa_next; // 遍历下一个接口}if (NULL != oifa) {freeifaddrs(oifa); // 释放整个链表}
#endifreturn ""; // 未找到匹配接口
}

💎 关键设计总结

  1. 跨平台兼容性
    • 通过 #if 确保 Android 低版本不编译此逻辑。
  2. 资源安全管理
    • 使用 oifa 备份链表头,确保任何退出路径都能正确释放内存。
  3. 双协议栈支持
    • 独立处理 IPv4/IPv6 地址,通过 memcmp 精确匹配 IPv6 地址。
  4. 高效遍历
    • 链表遍历在匹配成功后立即退出,避免无效搜索。

提示:实际使用时需确保 IPEndPoint 类正确实现 GetAddress()(IPv4)和 GetAddressBytes()(IPv6)方法。


文章转载自:

http://bWp75cjP.xjpnq.cn
http://eu6wMW8J.xjpnq.cn
http://bvHeFBR3.xjpnq.cn
http://Uxee5KyF.xjpnq.cn
http://oJSgKSgd.xjpnq.cn
http://wM55i5RR.xjpnq.cn
http://EjC78rUB.xjpnq.cn
http://d0HjXkTs.xjpnq.cn
http://4lhUOFcF.xjpnq.cn
http://19G4OjDd.xjpnq.cn
http://R47gpz1X.xjpnq.cn
http://1xRM0y2V.xjpnq.cn
http://FVQAcmGB.xjpnq.cn
http://enFV5mcd.xjpnq.cn
http://FDWjfy9P.xjpnq.cn
http://fjaWZltd.xjpnq.cn
http://UnGxN89q.xjpnq.cn
http://HAGLfBde.xjpnq.cn
http://92wokqug.xjpnq.cn
http://lmtnYEqT.xjpnq.cn
http://Pbqpihva.xjpnq.cn
http://8KHNa7y4.xjpnq.cn
http://5OTfWP8D.xjpnq.cn
http://ENVGKmDR.xjpnq.cn
http://UTzEkB3s.xjpnq.cn
http://dP39EJIS.xjpnq.cn
http://FgeJG6oD.xjpnq.cn
http://UNlx2NwK.xjpnq.cn
http://BQBEfSJg.xjpnq.cn
http://VPQjSNM2.xjpnq.cn
http://www.dtcms.com/a/369066.html

相关文章:

  • EXCEL列数据前面补零
  • Big Data Analysis
  • 拿到一组数据在mars3d上渲染报错排查思路
  • 力扣hot100:搜索二维矩阵 II(常见误区与高效解法详解)(240)
  • 《从报错到运行:STM32G4 工程在 Keil 中的头文件配置与调试实战》
  • Meta AI眼镜Hypernova量产临近,微美全息构筑护城河引领人机交互变革浪潮
  • SQL表一共有几种写入方式
  • Vue3源码reactivity响应式篇之ReactiveEffect类
  • C++中的Reactor和Proactor模型进行系统性解析
  • 调试技巧:Chrome DevTools 与 Node.js Inspector
  • 双碳目标下的24小时分时综合能源系统低碳优化调度:基于 Matlab/YALMIP/CPLEX的方法与仿真
  • 告别 “无效阅读”!2025 开学季超赞科技书单,带孩子解锁 AI、编程新技能
  • 鸿蒙Next的UI国际化与无障碍适老化实践:构建全球包容的数字世界
  • react 全屏页面自适应操作,注意问题
  • 计算机毕设选题:基于Python数据挖掘的高考志愿推荐系统
  • PCL中的特征提取
  • 2025年TOP8最佳GNSS位移监测设备权威推荐榜单
  • 告别研发内耗!这款免费项目管理工具,让团队效率实现 3 倍跃升
  • 【智慧城市】2025年中国地质大学(武汉)暑期实训优秀作品(3):基于Mapbox GL JS 构建的城市三维可视化系统
  • 图像处理:实现多图点重叠效果
  • 在Kingbase数据库中指定用户模式并查看拥有的数据库模式
  • 【TXT】用 Python 实现超漂亮的 HTML 两栏文本对比工具(支持行内差异高亮)
  • VOGUE二十周年女演员群像封面
  • 使用pytorch创建/训练/推理OCR模型
  • 从音频到文本实现高精度离线语音识别
  • 安防芯片ISP白平衡统计数据如何提升场景适应性?
  • Spring如何解决循环依赖:深入理解三级缓存机制
  • 当服务器出现网卡故障时如何检测网卡硬件故障并解决?
  • 【算法--链表】83.删除排序链表中的重复元素--通俗讲解
  • Grafana 导入仪表盘失败:从日志排查到解决 max\_allowed\_packet 问题