Linux C API 获取本机的 IP 地址
方法1:遍历网卡
#include <stdio.h>      
#include <ifaddrs.h>
#include <arpa/inet.h>
int main (void) 
{
    struct ifaddrs* ifAddrStruct = NULL;
    getifaddrs(&ifAddrStruct); // 获得网卡的链表
    while (ifAddrStruct!=NULL) 
    {
        if (ifAddrStruct->ifa_addr->sa_family==AF_INET) 
        {
            // IPv4
            char address[INET_ADDRSTRLEN];
            void* inAddr = &((struct sockaddr_in *)ifAddrStruct->ifa_addr)->sin_addr;
            inet_ntop(AF_INET, inAddr, address, INET_ADDRSTRLEN);
            
            char netMask[INET_ADDRSTRLEN];
            void* inNetMask = &((struct sockaddr_in *)ifAddrStruct->ifa_netmask)->sin_addr;
            inet_ntop(AF_INET, inNetMask, netMask, INET_ADDRSTRLEN);
            
            char broadAddr[INET_ADDRSTRLEN];
            void* inBroadAddr = &((struct sockaddr_in *)ifAddrStruct->ifa_ifu.ifu_broadaddr)->sin_addr;
            inet_ntop(AF_INET, inBroadAddr, broadAddr, INET_ADDRSTRLEN);
            
            printf("IPv4 %8s: %31s \t%31s \t%31s\n", ifAddrStruct->ifa_name, address, netMask, broadAddr); 
        } 
        else if (ifAddrStruct->ifa_addr->sa_family==AF_INET6) 
        {
            // IPv6
            char address[INET6_ADDRSTRLEN];
            void* inAddr = &((struct sockaddr_in *)ifAddrStruct->ifa_addr)->sin_addr;
            inet_ntop(AF_INET6, inAddr, address, INET6_ADDRSTRLEN);
            
            char prefixMask[INET6_ADDRSTRLEN];
            void* inPrefixMask = &((struct sockaddr_in *)ifAddrStruct->ifa_netmask)->sin_addr;
            inet_ntop(AF_INET6, inPrefixMask, prefixMask, INET6_ADDRSTRLEN);
            
            printf("IPv6 %8s: %31s \t%31s\n", ifAddrStruct->ifa_name, address, prefixMask); 
        } 
        ifAddrStruct=ifAddrStruct->ifa_next;
    }
    return 0;
}
方法2:gethostbyname
这个方法不能支持 IPv6
#include <stdio.h>    
#include <unistd.h>  
#include <netdb.h>
#include <arpa/inet.h>
int main (void) 
{
    // 获取 host name
    char hostName[_SC_HOST_NAME_MAX];
    gethostname(hostName, _SC_HOST_NAME_MAX);
    // 通过 host name 获取 host entry
    struct hostent* hostEntry = gethostbyname(hostName);
    // 打印 IP 地址
    for(int i = 0; hostEntry->h_addr_list[i]; i++) 
    {
        printf("%s\n", inet_ntoa(*(struct in_addr*)(hostEntry->h_addr_list[i])));
    }
    return 0;
}
在
netdb.h中还有一个gethostent函数,能够遍历 host entry,但是它只能查询/etc/hosts里的值。因此,它通常只能返回127.0.0.1#include <stdio.h> #include <unistd.h> #include <netdb.h> #include <arpa/inet.h> int main(void) { struct hostent* hostEntry; while((hostEntry = gethostent()) != NULL) { for(int i = 0; hostEntry->h_addr_list[i]; i++) { printf("%s\n", inet_ntoa(*(struct in_addr*)(hostEntry->h_addr_list[i]))); } } return 0; }