第一部分 获取本机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;
}
其中涉及到的方法,包括in_addr和点分十进制IP地址之间转换的方法
#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
};