C语言动态获取设备的网络接口名称和状态以及对应的IP地址

一、目的

        在实际项目中需要获取设备的IP地址然后通过广播的形式通知局域网内的其他设备。

二、介绍

        方法一

        通过ioctl方式获取SIOCGIFADDR信息

/*
 * C Program to Get IP Address
 */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc, char **argv)
{
    int n;
    struct ifreq ifr;
    char *inf = argv[1];

    n = socket(AF_INET, SOCK_DGRAM, 0);
    //Type of address to retrieve - IPv4 IP address
    ifr.ifr_addr.sa_family = AF_INET;
    //Copy the interface name in the ifreq structure
    strncpy(ifr.ifr_name, inf, IFNAMSIZ - 1);
    ioctl(n, SIOCGIFADDR, &ifr);
    close(n);
    //display result
    printf("IP Address is %s - %s\n" , inf , inet_ntoa(( (struct sockaddr_in *)&ifr.ifr_addr )->sin_addr) );
    return 0;
}

        

gcc getip.c -o getip

         

         这种方法的前提是必须知道网络接口名称,比如enp1s0或者eth0

        参考资料

netdevice(7) - Linux manual pageicon-default.png?t=N658https://man7.org/linux/man-pages/man7/netdevice.7.html

 

        方法二         

        通过函数getaddrinfo实现

        在正式介绍之前,我们先介绍一下ifconfig -a的输出各个字段的含义

C语言动态获取设备的网络接口名称和状态以及对应的IP地址_第1张图片        

 

#include 
#include 

/*
获取网络接口链表
*/
int getifaddrs(struct ifaddrs **ifap);

/*
释放网络接口链表
*/
void freeifaddrs(struct ifaddrs *ifa);

struct ifaddrs {
    struct ifaddrs  *ifa_next;    /* Next item in list */
    char            *ifa_name;    /* Name of interface */
    unsigned int     ifa_flags;   /* Flags from SIOCGIFFLAGS */
    struct sockaddr *ifa_addr;    /* Address of interface */
    struct sockaddr *ifa_netmask; /* Netmask of interface */
    union {
        struct sockaddr *ifu_broadaddr;
                                    /* Broadcast address of interface */
        struct sockaddr *ifu_dstaddr;
                                    /* Point-to-point destination address */
    } ifa_ifu;
    #define              ifa_broadaddr ifa_ifu.ifu_broadaddr
    #define              ifa_dstaddr   ifa_ifu.ifu_dstaddr
    void            *ifa_data;    /* Address-specific data */
    };

         各个字段含义:

        ifa_next:下一个接口的地址

        ifa_name:接口名称,例如"eth0"、"lo"

        ifa_flags:接口属性状态标志

                C语言动态获取设备的网络接口名称和状态以及对应的IP地址_第2张图片

        ifa_addr:接口的IP地址(ipv4/ipv6),当接口不在工作时该指针为NULL

        ifa_netmask:接口的子网掩码

        ifa_broadaddr:如果支持广播,此字段记录广播地址信息

        ifa_dstaddr:如果支持点对点通信,此字段记录对端地址

                

三、实战

        

#define _GNU_SOURCE     /* To get defns of NI_MAXSERV and NI_MAXHOST */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc, char *argv[])
{
	struct ifaddrs *ifaddr, *ifa;
	int family, s, n;
	char host[NI_MAXHOST];

	if (getifaddrs(&ifaddr) == -1) {
		perror("getifaddrs");
		exit(EXIT_FAILURE);
	}

	/* Walk through linked list, maintaining head pointer so we
	   can free list later */

#if 1
	for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
		if (ifa->ifa_addr == NULL)
			continue;

		printf("======1\n");
		family = ifa->ifa_addr->sa_family;

		/* Display interface name and family (including symbolic
		   form of the latter for the common families) */

		printf("%-8s %s (%d)\n",
				ifa->ifa_name,
				(family == AF_PACKET) ? "AF_PACKET" :
				(family == AF_INET) ? "AF_INET" :
				(family == AF_INET6) ? "AF_INET6" : "???",
				family);

		/* For an AF_INET* interface address, display the address */

		printf("======2\n");
		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("\t\taddress: <%s>\n", host);

		} else if (family == AF_PACKET && ifa->ifa_data != NULL) {
			struct rtnl_link_stats *stats = ifa->ifa_data;

			printf("\t\ttx_packets = %10u; rx_packets = %10u\n"
					"\t\ttx_bytes   = %10u; rx_bytes   = %10u\n",
					stats->tx_packets, stats->rx_packets,
					stats->tx_bytes, stats->rx_bytes);
		}
		printf("======3\n");
	}
#else
	for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
		if (ifa->ifa_addr == NULL)
			continue;
		family = ifa->ifa_addr->sa_family;
		unsigned int flags = ifa->ifa_flags;
		if (family == AF_INET && (flags & (IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_MULTICAST))) {
			if (0 == strcmp(ifa->ifa_name, argv[1])) {
				s = getnameinfo(ifa->ifa_addr,
						sizeof(struct sockaddr_in),
						host, NI_MAXHOST,
						NULL, 0, NI_NUMERICHOST);
				if (s != 0) {
					printf("getnameinfo() failed: %s\n", gai_strerror(s));
					exit(EXIT_FAILURE);
				}
				printf("\t\taddress: <%s>\n", host);
			}
		}
	}
#endif

	freeifaddrs(ifaddr);
	exit(EXIT_SUCCESS);
}

        C语言动态获取设备的网络接口名称和状态以及对应的IP地址_第3张图片

 

你可能感兴趣的:(c/c++,网络,c语言,嵌入式硬件)