Linux C 网络编程 - 获取本地 ip 地址,mac,通过域名获取对应的 ip
获取本地 ip 地址,mac,通过域名获取对应的 ip,
是网络编程可能遇到的比较常见的操作了,所以总结如下(封装了3个函数),
直接上代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <errno.h> 5 #include <unistd.h> 6 7 #include <netdb.h> 8 #include <net/if.h> 9 #include <arpa/inet.h> 10 #include <sys/ioctl.h> 11 #include <sys/types.h> 12 #include <sys/socket.h> 13 14 #define MAC_SIZE 18 15 #define IP_SIZE 16 16 17 // function declare 18 int get_ip_by_domain(const char *domain, char *ip); // 根据域名获取ip 19 int get_local_mac(const char *eth_inf, char *mac); // 获取本机mac 20 int get_local_ip(const char *eth_inf, char *ip); // 获取本机ip 21 22 23 /****** main test **********/ 24 int main(void) 25 { 26 char ip[IP_SIZE]; 27 char mac[MAC_SIZE]; 28 const char *test_domain = "www.baidu.com"; 29 const char *test_eth = "eth0"; 30 31 get_ip_by_domain(test_domain, ip); 32 printf("%s ip: %s\n", test_domain, ip); 33 34 get_local_mac(test_eth, mac); 35 printf("local %s mac: %s\n", test_eth, mac); 36 37 get_local_ip(test_eth, ip); 38 printf("local %s ip: %s\n", test_eth, ip); 39 40 return 0; 41 } 42 43 // 根据域名获取ip 44 int get_ip_by_domain(const char *domain, char *ip) 45 { 46 char **pptr; 47 struct hostent *hptr; 48 49 hptr = gethostbyname(domain); 50 if(NULL == hptr) 51 { 52 printf("gethostbyname error for host:%s/n", domain); 53 return -1; 54 } 55 56 for(pptr = hptr->h_addr_list ; *pptr != NULL; pptr++) 57 { 58 if (NULL != inet_ntop(hptr->h_addrtype, *pptr, ip, IP_SIZE) ) 59 { 60 return 0; // 只获取第一个 ip 61 } 62 } 63 64 return -1; 65 } 66 67 // 获取本机mac 68 int get_local_mac(const char *eth_inf, char *mac) 69 { 70 struct ifreq ifr; 71 int sd; 72 73 bzero(&ifr, sizeof(struct ifreq)); 74 if( (sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 75 { 76 printf("get %s mac address socket creat error\n", eth_inf); 77 return -1; 78 } 79 80 strncpy(ifr.ifr_name, eth_inf, sizeof(ifr.ifr_name) - 1); 81 82 if(ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) 83 { 84 printf("get %s mac address error\n", eth_inf); 85 close(sd); 86 return -1; 87 } 88 89 snprintf(mac, MAC_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x", 90 (unsigned char)ifr.ifr_hwaddr.sa_data[0], 91 (unsigned char)ifr.ifr_hwaddr.sa_data[1], 92 (unsigned char)ifr.ifr_hwaddr.sa_data[2], 93 (unsigned char)ifr.ifr_hwaddr.sa_data[3], 94 (unsigned char)ifr.ifr_hwaddr.sa_data[4], 95 (unsigned char)ifr.ifr_hwaddr.sa_data[5]); 96 97 close(sd); 98 99 return 0; 100 } 101 102 103 // 获取本机ip 104 int get_local_ip(const char *eth_inf, char *ip) 105 { 106 int sd; 107 struct sockaddr_in sin; 108 struct ifreq ifr; 109 110 sd = socket(AF_INET, SOCK_DGRAM, 0); 111 if (-1 == sd) 112 { 113 printf("socket error: %s\n", strerror(errno)); 114 return -1; 115 } 116 117 strncpy(ifr.ifr_name, eth_inf, IFNAMSIZ); 118 ifr.ifr_name[IFNAMSIZ - 1] = 0; 119 120 // if error: No such device 121 if (ioctl(sd, SIOCGIFADDR, &ifr) < 0) 122 { 123 printf("ioctl error: %s\n", strerror(errno)); 124 close(sd); 125 return -1; 126 } 127 128 memcpy(&sin, &ifr.ifr_addr, sizeof(sin)); 129 snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr)); 130 131 close(sd); 132 return 0; 133 }
测试运行
结果如下:
ifreq 结构体分析和使用:
1 struct ifreq 2 { 3 #define IFHWADDRLEN 6 4 union 5 { 6 char ifrn_name[IFNAMSIZ]; 7 } ifr_ifrn; 8 9 union { 10 struct sockaddr ifru_addr; 11 struct sockaddr ifru_dstaddr; 12 struct sockaddr ifru_broadaddr; 13 struct sockaddr ifru_netmask; 14 struct sockaddr ifru_hwaddr; 15 short ifru_flags; 16 int ifru_ivalue; 17 int ifru_mtu; 18 struct ifmap ifru_map; 19 char ifru_slave[IFNAMSIZ]; 20 char ifru_newname[IFNAMSIZ]; 21 void __user * ifru_data; 22 struct if_settings ifru_settings; 23 } ifr_ifru; 24 }; 25 26 #define ifr_name ifr_ifrn.ifrn_name 27 #define ifr_hwaddr ifr_ifru.ifru_hwaddr 28 #define ifr_addr ifr_ifru.ifru_addr 29 #define ifr_dstaddr ifr_ifru.ifru_dstaddr 30 #define ifr_broadaddr ifr_ifru.ifru_broadaddr 31 #define ifr_netmask ifr_ifru.ifru_netmask 32 #define ifr_flags ifr_ifru.ifru_flags 33 #define ifr_metric ifr_ifru.ifru_ivalue 34 #define ifr_mtu ifr_ifru.ifru_mtu 35 #define ifr_map ifr_ifru.ifru_map 36 #define ifr_slave ifr_ifru.ifru_slave 37 #define ifr_data ifr_ifru.ifru_data 38 #define ifr_ifindex ifr_ifru.ifru_ivalue 39 #define ifr_bandwidth ifr_ifru.ifru_ivalue 40 #define ifr_qlen ifr_ifru.ifru_ivalue 41 #define ifr_newname ifr_ifru.ifru_newname 42 #define ifr_settings ifr_ifru.ifru_settings
基本介绍:
ifreq结构定义在/usr/include/net/if.h,用来配置ip地址,激活接口,配置MTU等接口信息的。其中包含了一个接口的名 字和具体内容——(是个共用体,有可能是IP地址,广播地址,子网掩码,MAC号,MTU或其他内容)。ifreq包含在ifconf结构中。而 ifconf结构通常是用来保存所有接口的信息的。
举例说明:
在Linux系统中,ifconfig命令是通过ioctl接口与内核通信,例如,当系统管理员输入如下命令来改变接口eth0的MTU大小:
ifconfig eth0 mtu 1250
ifconfig命令首先打开一个socket,然后通过系统管理员输入的参数初始化一个数据结构,并通过ioctl调用将数据传送到内核。SIOCSIFMTU是命令标识符。
struct ifreq data;
fd = socket(PF_INET, SOCK_DGRAM, 0);
< ... initialize "data" ...>
err = ioctl(fd, SIOCSIFMTU, &data);