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

Unix/Linux 高效的平台通过 IP 地址获取接口名的 C++ 构建

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);
// 释放整个接口链表
}
#endif
return "";
// 未找到匹配接口
}

收尾处理

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

完整代码实现

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);
// 释放整个链表
}
#endif
return "";
// 未找到匹配接口
}

关键设计总结

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

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

http://www.agseo.cn/news/24/

相关文章:

  • 每周读书与学习-初识JMeter 元件(一)
  • CloudBeaver轻量级的云数据库管理工具
  • kylin V10使用安装盘制作本地镜像
  • ArchVizTools Generators Collection 插件合集:3ds Max 建筑可视化神器(2018–2026 适用)
  • 初识python:一些基础的知识(六)
  • 进程注入
  • 告别框架臃肿-我如何在不牺牲性能的情况下重新发现简单之美
  • 自动点击网课确定按钮刷网课
  • 实时通信的头痛-问题不在WebSocket而是你的框架
  • 别再猜了-开始测量吧-一份实用的Web性能指南
  • Cisco Nexus Dashboard 4.1(1g) - 云和数据中心网络管理软件
  • mysql备份详解
  • Cisco NX-OS 10.6(1)F 发布 - 数据中心网络操作系统
  • 开源浪潮激荡,智驱能源革新:MyEMS 如何破局重塑能源管理新范式
  • 软件工程第一次作业
  • 在 Amazon Athena 中使用 Java 自定义 UDF
  • Tenda AC20路由器缓冲区溢出漏洞分析
  • 做题笔记 02
  • 实用指南:[网络入侵AI检测] docs | 任务二分类与多分类