机器多个网卡或者绑定多个ip时,
获取机器IP信息:
ifaddrs的结构如下
1: struct ifaddrs
2: {
3: struct ifaddrs *ifa_next; /* Next item in list */
4: char *ifa_name; /* Name of interface */
5: unsigned int ifa_flags; /* Flags from SIOCGIFFLAGS */
6: struct sockaddr *ifa_addr; /* Address of interface */
7: struct sockaddr *ifa_netmask; /* Netmask of interface */
8: union
9: {
10: struct sockaddr *ifu_broadaddr; /* Broadcast address of interface */
11: struct sockaddr *ifu_dstaddr; /* Point-to-point destination address */
12: } ifa_ifu;
13: #define ifa_broadaddr ifa_ifu.ifu_broadaddr
14: #define ifa_dstaddr ifa_ifu.ifu_dstaddr
15: void *ifa_data; /* Address-specific data */
16: };
ifa_next指向链表的下一个成员;ifa_name是接口名称,以0结尾的字符串,比如eth0,lo;ifa_flags是接口的标识位(比如当IFF_BROADCAST或IFF_POINTOPOINT设置到此标识位时,影响联合体变量ifu_broadaddr存储广播地址或ifu_dstaddr记录点对点地址);ifa_netmask存储该接口的子网掩码;结构体变量存储广播地址或点对点地址(见括弧介绍ifa_flags);ifa_data存储了该接口协议族的特殊信息,它通常是NULL(一般不关注他)。
函数getifaddrs(int getifaddrs (struct ifaddrs **__ifap))获取本地网络接口信息,将之存储于链表中,链表头结点指针存储于__ifap中带回,函数执行成功返回0,失败返回-1,且为errno赋值。
同时注意通过getifaddrs 返库ide指针需要手动释放,通过freeifaddrs(ifaddr);
代码示例如下:
1: #include <arpa/inet.h>
2: #include <ifaddrs.h>
3: #include <netinet/in.h>
4:
5: std::string FLAGS_ip_option = "IPV4"; // IPV4,IPV6,ALL
6: std::string FLAGS_skip_if_name = "eth1,lo"; // eth name want to skip
7: void GetLocalIPAddrs(vector<string>* ip_list) {
8: struct ifaddrs* if_addrs = NULL;
9: struct ifaddrs* ifa = NULL;
10: void* tmp_if_addr = NULL;
11: getifaddrs(&if_addrs);
12: for (ifa = if_addrs; ifa != NULL; ifa = ifa->ifa_next) {
13: if (FLAGS_skip_if_name.find(ifa->ifa_name) != string::npos) { // skip eth
14: continue;
15: }
16: if (FLAGS_ip_option == "ALL" || FLAGS_ip_option == "IPV4") {
17: if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IPV4
18: tmp_if_addr = &((struct sockaddr_in*)ifa->ifa_addr)->sin_addr; // NOLINT
19: char addr_buffer[INET_ADDRSTRLEN];
20: inet_ntop(AF_INET, tmp_if_addr, addr_buffer, INET_ADDRSTRLEN);
21: string ip(addr_buffer);
22: ip_list->push_back(ip);
23: }
24: }
25: if (FLAGS_ip_option == "ALL" || FLAGS_ip_option == "IPV6") {
26: if (ifa->ifa_addr->sa_family == AF_INET6) { // check it is IPV6
27: tmp_if_addr = &((struct sockaddr_in*)ifa->ifa_addr)->sin_addr; // NOLINT
28: char addr_buffer[INET6_ADDRSTRLEN];
29: inet_ntop(AF_INET6, tmp_if_addr, addr_buffer, INET6_ADDRSTRLEN);
30: string ip(addr_buffer);
31: ip_list->push_back(ip);
32: }
33: }
34: }
35: if (if_addrs != NULL) {
36: freeifaddrs(if_addrs);
37: }
38: }