C程序查找IP地址、子网掩码和默认网关

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;

}

后端开发标签