一、getifaddrs简介
getifaddrs是一种系统级函数,可用于检索网络接口的地址信息。其定义在ifaddrs.h头文件中。该函数通过动态分配存储空间来保存设备地址列表。通常情况下,您需要使用freeifaddrs函数释放该列表。
struct ifaddrs { struct ifaddrs *ifa_next; /* 下一个地址 */ char *ifa_name; /* 名称,任务类型,和类型信息 */ unsigned int ifa_flags; /* 属性 */ struct sockaddr *ifa_addr; /* 地址信息 */ struct sockaddr *ifa_netmask; /* 网络掩码 */ union { struct sockaddr *ifu_broadaddr; /* 广播地址 */ struct sockaddr *ifu_dstaddr; /* 目标地址 */ } ifa_ifu; #define ifa_broadaddr ifa_ifu.ifu_broadaddr #define ifa_dstaddr ifa_ifu.ifu_dstaddr void *ifa_data; /* 地址信息 */ };
二、使用getifaddrs函数
下面是使用getifaddrs函数的基本步骤:
1、定义一个ifaddrs类型指针,用于存储指向设备地址列表的第一个元素的指针。
2、调用getifaddrs函数,并将指向ifaddrs类型指针的指针传递给函数。
3、遍历设备地址列表,并执行所需操作。
4、最终执行freeifaddrs函数,以释放分配给设备地址列表的存储空间。
三、getifaddrs的特性
1、获取网络接口信息
使用getifaddrs函数可获取网络接口的信息,包括接口名称、IP地址、子网掩码等。此外,还可以轻松获取相关的网络接口的广播地址和目标地址。
struct ifaddrs *ifaddr, *ifa; int family, s; char host[NI_MAXHOST]; if (getifaddrs(&ifaddr) == -1) { perror("getifaddrs"); exit(EXIT_FAILURE); } for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; family = ifa->ifa_addr->sa_family; /* 显示地址族(针对IPV4和IPV6),IPV4地址和端口号,IPV6地址和端口号,并将地址存储在host数组中 */ if (family == AF_INET || family == AF_INET6) { s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (s != 0) { printf("getnameinfo() failed: %s\n", gai_strerror(s)); exit(EXIT_FAILURE); } printf("%s address: %s\n", ifa->ifa_name, host); } } freeifaddrs(ifaddr);
2、实现TCP/IP Server / Client 套接字列表
使用getifaddrs函数,可以轻松实现TCP/IP服务器和客户端套接字列表。下面是实现TCP/IP服务器/客户端套接字列表的代码示例。
int sockfd, status, s, max_fds = 0; struct addrinfo hints, *servinfo, *p; struct ifaddrs *ifaddr, *ifa; /* 获取可用地址列表 */ getifaddrs(&ifaddr); /* 循环连接可用地址 */ for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET) { continue; } /* 定义TCP/IP Socket服务器地址 */ memset(&hints, 0, sizeof hints); hints.ai_family = AF_INET; /* IPV4 */ hints.ai_socktype = SOCK_STREAM; /* 流套接字(比如TCP) */ hints.ai_flags = AI_PASSIVE; /* 意味着底层套接字地址将被用于bind调用中data */ /* 获取可用服务器地址 */ s = getaddrinfo(NULL, "8080", &hints, &servinfo); if (s != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); return -1; } /* 循环连接可用地址 */ for (p = servinfo; p != NULL; p = p->ai_next) { /* 创建TCP/IP Socket */ sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (sockfd ai_addr, p->ai_addrlen); if (status < 0) { close(sockfd); continue; } /* 监听客户端 */ status = listen(sockfd, 10); if (status < 0) { close(sockfd); continue; } /* 记录最大的文件描述符号码 */ max_fds = MAX(max_fds, sockfd); } /* free the list */ freeaddrinfo(servinfo); } freeifaddrs(ifaddr);
四、Getifaddrs崩溃
在使用getifaddrs时,一些安全漏洞可能导致崩溃。应该注意以下问题:
1、内存泄漏
必须使用freeifaddrs函数显式释放分配的内存。否则可能会导致内存泄漏。
2、缓冲区溢出
缓冲区溢出是指将输入数据存储在内存缓冲区之外的情况。这可能导致程序失败或崩溃。可以使用lwip中的替代方案lwip_getifaddrs避免此问题。
结论
getifaddrs是一种用于检索网络接口地址信息的系统级函数。通过动态分配存储空间来保存设备地址列表。使用该函数,您可以轻松实现TCP/IP服务器和客户端套接字列表、获取网络接口信息等。但是,在使用getifaddrs时,必须注意避免内存泄漏和缓冲区溢出引起的崩溃问题。
原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/309824.html