c 如何获取内网的ip地址
- 行业动态
- 2025-02-16
- 3703
ipconfig
命令来获取内网IP地址;在Linux或macOS系统中,可使用
ifconfig
或
ip addr
命令查看。
在C语言中获取内网IP地址是一个常见需求,特别是在网络编程和系统管理中,下面将详细介绍几种常用的方法来实现这一目标,包括使用gethostname
和gethostbyname
函数、getifaddrs
函数以及通过套接字接口查询等。
一、使用gethostname
和gethostbyname
函数
原理
这种方法首先通过gethostname
函数获取当前主机的主机名,然后使用gethostbyname
函数将主机名解析为IP地址。
实现步骤
获取主机名:调用gethostname
函数,将主机名存储在一个字符数组中。
解析主机名:使用gethostbyname
函数将主机名解析为一个hostent
结构体,该结构体包含了主机的IP地址信息。
转换为点分十进制格式:利用inet_ntoa
函数将网络字节序的IP地址转换为点分十进制格式的字符串。
示例代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <arpa/inet.h> #include <netdb.h> int main() { char hostname[256]; if (gethostname(hostname, sizeof(hostname)) == -1) { perror("gethostname"); exit(EXIT_FAILURE); } struct hostent *host_entry = gethostbyname(hostname); if (host_entry == NULL) { herror("gethostbyname"); exit(EXIT_FAILURE); } char *IPbuffer = inet_ntoa(*((struct in_addr*) host_entry->h_addr_list[0])); printf("本地IP地址: %s ", IPbuffer); return 0; }
二、使用`getifaddrs`函数
原理
getifaddrs
函数可以获取所有网络接口的详细信息,包括每个接口的IP地址。
实现步骤
引入头文件:包含必要的头文件,如<ifaddrs.h>
、<netinet/in.h>
、<arpa/inet.h>
等。
定义结构体指针:定义一个指向ifaddrs
结构体的指针,用于存储接口信息。
获取并遍历接口信息:调用getifaddrs
函数获取所有接口的信息,并遍历链表打印每个接口的IP地址,对于IPv4地址,可以通过检查ifa_addr->sa_family
是否等于AF_INET
来判断。
释放内存:使用完毕后,调用freeifaddrs
函数释放分配的内存。
示例代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ifaddrs.h> #include <arpa/inet.h> #include <netinet/in.h> int main() { struct ifaddrs *ifap, *ifa; if (getifaddrs(&ifap) == -1) { perror("getifaddrs"); exit(EXIT_FAILURE); } for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family == AF_INET) { // 只处理IPv4地址 char host[NI_MAXHOST]; if (getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) { printf("接口: %st地址: %s ", ifa->ifa_name, host); } } } freeifaddrs(ifap); return 0; }
三、通过套接字接口查询
原理
创建UDP套接字并连接到一个外部地址(如网关或DNS服务器),然后查询套接字的本地地址,这种方法适用于需要获取特定网络接口上的IP地址的情况。
实现步骤
创建套接字:使用socket
函数创建一个UDP套接字。
设置服务器地址:定义一个sockaddr_in
结构体作为服务器地址,通常设置为一个已知的外部地址。
连接套接字:调用connect
函数将套接字连接到服务器地址。
获取本地地址:使用getsockname
函数获取套接字的本地地址,即绑定到套接字的网络接口的IP地址。
关闭套接字:关闭套接字以释放资源。
示例代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/in.h> int main() { int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd == -1) { perror("socket"); exit(EXIT_FAILURE); } struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(80); // 任意选择一个端口号 inet_pton(AF_INET, "8.8.8.8", &serv_addr.sin_addr); // 使用Google的DNS服务器地址作为测试地址 if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) { perror("connect"); close(sockfd); exit(EXIT_FAILURE); } struct sockaddr_in local_addr; socklen_t addr_len = sizeof(local_addr); if (getsockname(sockfd, (struct sockaddr *)&local_addr, &addr_len) == -1) { perror("getsockname"); close(sockfd); exit(EXIT_FAILURE); } char local_ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &local_addr.sin_addr, local_ip, INET_ADDRSTRLEN); printf("本地IP地址: %s ", local_ip); close(sockfd); return 0; }
四、FAQs
Q1: 如何过滤掉不需要的网络接口?
A1: 在使用getifaddrs
函数时,可以通过检查接口名称来过滤掉不需要的网络接口,如果要过滤掉回环接口(lo),可以在遍历链表时加入条件判断,跳过名称为"lo"的接口,示例如下:
for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { if (strcmp(ifa->ifa_name, "lo") == 0) continue; // 跳过本地回环接口 // 其他处理逻辑... }
Q2: 如何同时获取IPv4和IPv6地址?
A2: 在使用getifaddrs
函数时,只需检查ifa_addr->sa_family
字段是否等于AF_INET
(表示IPv4)或AF_INET6
(表示IPv6),如果需要同时获取两种类型的地址,可以在遍历链表时分别处理,示例如下:
for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; if (ifa->ifa_addr->sa_family == AF_INET) { // IPv4地址处理逻辑 } else if (ifa->ifa_addr->sa_family == AF_INET6) { // IPv6地址处理逻辑 } }
本站发布或转载的文章及图片均来自网络,其原创性以及文中表达的观点和判断不代表本站,有问题联系侵删!
本文链接:http://www.xixizhuji.com/fuzhu/91273.html