一、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/zh-tw/n/309824.html