如何从C代码获取Linux上接口的IPv4地址?
例如,我想获取分配给eth0的IP地址(如果有)。
Answers:
尝试这个:
#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;
}
代码示例是从这里获取的。
SIOCGIFADDR
为SIOCGIFNETMASK
,则可以获取接口的网络掩码。
ioctl()
,如果非零,请检查的值errno
。
IFNAMSIZ-1
,而是IFNAMSIZ
足够了。万一发生溢出,strncpy将使用最后一个字节终止字符串。
strncpy
联机帮助页:警告:如果src的前n个字节中没有空字节,则放置在dest中的字符串将不以空值结尾。
除了ioctl()方法,Filip还演示了您可以使用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);
}
您可以将eth0替换为wlan0,将eth0替换为以太网,将lo替换为本地回送。
可以在此处找到所使用的数据结构的结构和详细说明。
要了解有关C中链表的更多信息,此页面将是一个很好的起点。
getnameinfo
?
host
稍后打印的参数值在getnameinfo
函数内部提供。
ifa->ifa_addr == NULL
还不够?我不确定为什么我们需要getnameinfo
ifa_addr是内部地址。
我的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
我只是删除了针对wlan0的测试以查看数据。ps您可以删除“家庭”
如果您不介意二进制大小,则可以使用iproute2作为库。
优点:
缺点: