獲取本地 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 }
測試運行dom
結果以下:socket
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結構一般是用來保存全部接口的信息的。spa
舉例說明:.net
在Linux系統中,ifconfig命令是經過ioctl接口與內核通訊,例如,當系統管理員輸入以下命令來改變接口eth0的MTU大小:code
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);