在 Linux 上获取接口的 IP 地址

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2283494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 19:46:24  来源:igfitidea点击:

Get IP address of an interface on Linux

clinuxsockets

提问by leeeroy

How can I get the IPv4address of an interface on Linux from C code?

如何从 C 代码获取Linux 上接口的IPv4地址?

For example, I'd like to get the IP address (if any) assigned to eth0.

例如,我想获取分配给 eth0 的 IP 地址(如果有)。

采纳答案by Filip Ekberg

Try this:

尝试这个:

#include <stdio.h>
#include <unistd.h>
#include <string.h> /* for strncpy */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>

int
main()
{
 int fd;
 struct ifreq ifr;

 fd = socket(AF_INET, SOCK_DGRAM, 0);

 /* I want to get an IPv4 IP address */
 ifr.ifr_addr.sa_family = AF_INET;

 /* I want IP address attached to "eth0" */
 strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1);

 ioctl(fd, SIOCGIFADDR, &ifr);

 close(fd);

 /* display result */
 printf("%s\n", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));

 return 0;
}

The code sample is taken from here.

代码示例取自此处

回答by Duck

In addition to the ioctl() method Filip demonstrated you can use getifaddrs(). There is an example program at the bottom of the man page.

除了 Filip 演示的 ioctl() 方法之外,您还可以使用getifaddrs()。手册页底部有一个示例程序。

回答by sjsam

If you're looking for an address (IPv4) of the specific interface say wlan0then try this code which uses getifaddrs():

如果您正在寻找特定接口的地址(IPv4),例如wlan0,请尝试使用getifaddrs() 的代码:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
    struct ifaddrs *ifaddr, *ifa;
    int family, s;
    char host[NI_MAXHOST];

    if (getifaddrs(&ifaddr) == -1) 
    {
        perror("getifaddrs");
        exit(EXIT_FAILURE);
    }


    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) 
    {
        if (ifa->ifa_addr == NULL)
            continue;  

        s=getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in),host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);

        if((strcmp(ifa->ifa_name,"wlan0")==0)&&(ifa->ifa_addr->sa_family==AF_INET))
        {
            if (s != 0)
            {
                printf("getnameinfo() failed: %s\n", gai_strerror(s));
                exit(EXIT_FAILURE);
            }
            printf("\tInterface : <%s>\n",ifa->ifa_name );
            printf("\t  Address : <%s>\n", host); 
        }
    }

    freeifaddrs(ifaddr);
    exit(EXIT_SUCCESS);
}

You can replace wlan0with eth0for ethernet and lofor local loopback.

您可以将wlan0替换为eth0用于以太网和lo用于本地环回。

The structure and detailed explanations of the data structures used could be found here.

可以在此处找到所用数据结构的结构和详细说明。

To know more about linked list in C this pagewill be a good starting point.

要了解有关 C 中链表的更多信息,此页面将是一个很好的起点。

回答by ingconti

My 2 cents: the same code works even if iOS:

我的 2 美分:即使 iOS 也能使用相同的代码:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>



#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    showIP();
}



void showIP()
{
    struct ifaddrs *ifaddr, *ifa;
    int family, s;
    char host[NI_MAXHOST];

    if (getifaddrs(&ifaddr) == -1)
    {
        perror("getifaddrs");
        exit(EXIT_FAILURE);
    }


    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
    {
        if (ifa->ifa_addr == NULL)
            continue;

        s=getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in),host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);

        if( /*(strcmp(ifa->ifa_name,"wlan0")==0)&&( */ ifa->ifa_addr->sa_family==AF_INET) // )
        {
            if (s != 0)
            {
                printf("getnameinfo() failed: %s\n", gai_strerror(s));
                exit(EXIT_FAILURE);
            }
            printf("\tInterface : <%s>\n",ifa->ifa_name );
            printf("\t  Address : <%s>\n", host);
        }
    }

    freeifaddrs(ifaddr);
}


@end

I simply removed the test against wlan0 to see data. ps You can remove "family"

我只是删除了针对 wlan0 的测试以查看数据。ps 您可以删除“家庭”

回答by eshenhu

If you don't mind the binary size, you can use iproute2 as library.

如果你不介意二进制大小,你可以使用 iproute2 作为库。

iproute2-as-lib

iproute2-as-lib

Pros:

优点:

  • No need to write the socket layer code.
  • More or even more information about network interfaces can be got. Same functionality with the iproute2 tools.
  • Simple API interface.
  • 无需编写套接字层代码。
  • 可以获得更多甚至更多关于网络接口的信息。与 iproute2 工具的功能相同。
  • 简单的API接口。

Cons:

缺点:

  • iproute2-as-lib library size is big. ~500kb.
  • iproute2-as-lib 库的大小很大。~500kb。