1. 概述
IP地址、子网掩码、默认网关是网络中常见的概念,它们在网络通信中起着重要的作用。本文将介绍如何使用C语言查找IP地址、子网掩码和默认网关。
2. 获取网络接口信息
在C语言中,可以使用getifaddrs()
函数获取当前系统中的网络接口信息,包括IP地址、子网掩码、默认网关等信息。
下面是使用getifaddrs()
函数获取网络接口信息的示例代码:
#include <ifaddrs.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
int main()
{
struct ifaddrs *ifaddr, *ifa;
if (getifaddrs(&ifaddr) == -1)
{
perror("getifaddrs");
exit(EXIT_FAILURE);
}
// 遍历链表
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr == NULL)
continue;
// 获取IP地址
if (ifa->ifa_addr->sa_family == AF_INET)
{
struct sockaddr_in *sa = (struct sockaddr_in *) ifa->ifa_addr;
char *addr = inet_ntoa(sa->sin_addr);
printf("%s: %s\n", ifa->ifa_name, addr);
}
// 获取子网掩码
if (ifa->ifa_netmask != NULL && ifa->ifa_addr->sa_family == AF_INET)
{
struct sockaddr_in *sa = (struct sockaddr_in *) ifa->ifa_netmask;
char *mask = inet_ntoa(sa->sin_addr);
printf("%s: %s\n", ifa->ifa_name, mask);
}
// 获取默认网关
if (ifa->ifa_flags & IFF_UP && ifa->ifa_flags & IFF_RUNNING && ifa->ifa_dstaddr != NULL)
{
if (ifa->ifa_dstaddr->sa_family == AF_INET)
{
struct sockaddr_in *sa = (struct sockaddr_in *) ifa->ifa_dstaddr;
char *gw = inet_ntoa(sa->sin_addr);
printf("%s: %s\n", ifa->ifa_name, gw);
}
}
}
freeifaddrs(ifaddr);
return 0;
}
2.1 函数说明
getifaddrs(struct ifaddrs **ifap)
函数会把系统中所有的网络接口信息保存在ifaddrs
结构体链表中,第一个参数ifap
是一个指向指针的指针,该指针会指向ifaddrs
结构体链表的头部。
函数返回值为0表示成功,返回-1表示出错。
freeifaddrs(struct ifaddrs *ifa)
函数用于释放getifaddrs()
函数返回的动态分配的内存。
2.2 结构体说明
struct ifaddrs
结构体定义如下:
struct ifaddrs {
struct ifaddrs *ifa_next; //下一个接口
char *ifa_name; //接口名
unsigned int ifa_flags; //标志
struct sockaddr *ifa_addr; //地址
struct sockaddr *ifa_netmask; //掩码
struct sockaddr *ifa_dstaddr; //目的地址
void *ifa_data; //接口特定数据
};
其中,ifa_next
是指向下一个链表元素的指针,ifa_name
是接口名,ifa_flags
是接口标志,ifa_addr
是指向接口地址的指针,ifa_netmask
是指向接口掩码的指针,ifa_dstaddr
是指向接口目的地址的指针,ifa_data
是接口特定的数据。
3. 解析结果
获取到网络接口信息之后,我们需要对其进行解析,找出IP地址、子网掩码和默认网关。
IP地址和子网掩码都保存在struct sockaddr_in
结构体的sin_addr
成员中,可以通过inet_ntoa()
函数将其中的二进制表示转换成字符串。
默认网关的地址保存在ifa_dstaddr
成员中,所属的结构体类型也是struct sockaddr_in
,所以可以使用inet_ntoa()
函数进行转换。
4. 示例代码
这里再放一下完整的示例代码:
#include <ifaddrs.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
int main()
{
struct ifaddrs *ifaddr, *ifa;
if (getifaddrs(&ifaddr) == -1)
{
perror("getifaddrs");
exit(EXIT_FAILURE);
}
// 遍历链表
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr == NULL)
continue;
// 获取IP地址
if (ifa->ifa_addr->sa_family == AF_INET)
{
struct sockaddr_in *sa = (struct sockaddr_in *) ifa->ifa_addr;
char *addr = inet_ntoa(sa->sin_addr);
printf("%s: %s\n", ifa->ifa_name, addr);
}
// 获取子网掩码
if (ifa->ifa_netmask != NULL && ifa->ifa_addr->sa_family == AF_INET)
{
struct sockaddr_in *sa = (struct sockaddr_in *) ifa->ifa_netmask;
char *mask = inet_ntoa(sa->sin_addr);
printf("%s: %s\n", ifa->ifa_name, mask);
}
// 获取默认网关
if (ifa->ifa_flags & IFF_UP && ifa->ifa_flags & IFF_RUNNING && ifa->ifa_dstaddr != NULL)
{
if (ifa->ifa_dstaddr->sa_family == AF_INET)
{
struct sockaddr_in *sa = (struct sockaddr_in *) ifa->ifa_dstaddr;
char *gw = inet_ntoa(sa->sin_addr);
printf("%s: %s\n", ifa->ifa_name, gw);
}
}
}
freeifaddrs(ifaddr);
return 0;
}