第一部分 获取本机IP地址
#include<unistd.h> #include<netdb.h> #include<arpa/inet.h> string get_local_ip() { char hname[128]; struct hostent *hent; gethostname(hname, sizeof(hnameme)); hent = gethostbyname(hname); return inet_ntoa(*(struct in_addr *)(hent->h_addr)); }
其中各个函数以及结构体的用法:
#include <netdb.h> struct hostent { char *h_name; char *h_aliases; short h_addrtype; short h_length; char **h_addr_list; }; #define h_addr h_addr_list[0]; // 因为一个机器可能有多个网络接口,所以地址是一个链表,其中默认取的第一个。 #include <unistd.h> void gethostname(char *host_name, int name_len); // 返回主机的标准主机名 #include<netdb.h> struct hostent* gethostbyname(const char *host_name); // 返回对应于给定主机名的主机信息 #include<arap/inet.h> char *inet_ntoa(struct in_addr); // 返回点十进制的字符串在静态内存中的指针; // 功能:将网络地址转换成点分十进制的字符串 #include<arpa/inet.h> struct in_addr { in_addr_t s_addr; } // 结构体in_addr用来表示一个32位的IPv4地址,其中in_addr_t一般为32位的unsigned int,其字节顺序为网络顺序,即该无符号整数采用大端字节序。 struct in_addr { unio { struct { u_char s_b1, s_b2, s_b3, s_b4; } S_un_b; // An IPv4 address formatted as four u_chars. struct { u_short s_w1, s_w2; } S_un_w; // An IPv4 address formatted as two u_shorts. u_long S_addr; // An IPv4 address formatted as a u_long } S_un; #define s_addr S_un.S_addr };
第二部分 遍历网络接口信息,获取每个网卡的信息,包括IP地址
这样就可以根据指定的网卡获取相应的IP地址。
#include <iostream> #include<ifaddrs.h> #include<netinet/in.h> #include<arpa/inet.h> using namespace std; int main() { struct ifaddrs *if_addr_struct = NULL; void *tmp_addr_ptr = NULL; getifaddrs(&if_addr_struct); struct ifaddrs *if_addr_struct_orign = if_addr_struct; while (if_addr_struct != NULL) { if (if_addr_struct != NULL) { if (if_addr_struct->ifa_addr->sa_family == AF_INET) { // ipv4 tmp_addr_ptr = &((struct sockaddr_in *)if_addr_struct->ifa_addr)->sin_addr; char address[16]; inet_ntop(AF_INET, tmp_addr_ptr, address, sizeof(address)); cout << "Interface Name: " << if_addr_struct->ifa_name << endl; cout << "Interface IP: " << address << endl; } else if (if_addr_struct->ifa_addr->sa_family == AF_INET6) { // ipv6 tmp_addr_ptr = &((struct sockaddr_in *)if_addr_struct->ifa_addr)->sin_addr; char address[128]; inet_ntop(AF_INET6, tmp_addr_ptr, address, sizeof(address)); cout << "Interface Name: " << if_addr_struct->ifa_name << endl; cout << "Interface IP: "<< address << endl; } } if_addr_struct = if_addr_struct->ifa_next; } if (if_addr_struct_orign) { freeifaddrs(if_addr_struct_orign); } return 0; }
#include<arpa/inet.h> char *inet_ntoa(struct in_addr); //返回点分十进制的字符串在静态内存中的指针; //函数功能: 将网络地址转换成“.”间隔的字符串格式 int inet_aton(const char *string, struct in_addr *addr); // 将一个IP地址串转换成32位的网络序列IP地址 #include<arpa/inet.h> in_addr_t inet_addr(const char *ip); //将点分十进制的IP转换成一个长整形数(u_long类型); //函数功能:点分十进制IP转换成网络字节IP #include<arpa/inet.h> const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt); //将网络二进制结构到ASCII类型的地址,参数的作用和inet_pton相同 //将二进制整数转换成点分十进制,参数socklen_t指向dst缓冲区的大小,避免溢出。如果缓冲区太小,则返回空指针。并将errno置为ENOSPC。 int inet_pton(int af, const char *src, void *dst); //这个函数将字符串转换成网络地址,第一个参数af是地址族,第二个参数src是来源地址,第三个参数为转换后的数据 //inet_pton是inet_addr的扩展,支持多地址族 AF_INET、AF_INET6 /* 上述5个方法全部都是struct in_addr和点分十进制IP地址串之间的转换。其中前三个方法的缺陷就是,不能处理IPv6。 The function inet_ntoa() converts a network address in a struct in_addr to a dots-and-numbers format string. The "n" in nota stands for network, and the "a“ stands for ASCII for historical reasons(so it's "Network To ASCII"-the "toa" suffix has an analogous friend in C library called atoi() which converts ASCII string to integer. The function inet_aton is the opposite, converting from a dots-and-numbers string into a in_addr_t (which is the type of field s_addr in struct in_addr) The function inet_addr() is an older function that does basically the same thing as inet_aton(). 其中最后的inet_ntop()和inet_pton()是最新的。建议使用。 n表示network, p代表printable */
#include<ifaddrs.h> 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.ifa_dstaddr void *ifa_data; //address-specific data } //该结构体用于存放网络接口相关的所有参数,可以通过它查询IP地址等 struct sockaddr { unsigned short sa_family; //address family, AF_XXX char sa_char[14]; //14 bytes of protocol address }; #include<netinet/in.h> struct sockaddr_in { short int sin_family; //address family unsigned short int sin_port; //port number struct in_addr sin_addr; //internet address unsigned char sin_zero[8]; //same size as struct sockaddr };