获取计算机的本地网络IP地址是否有符合POSIX标准的方法?

3

我知道这个问题以某种形式被问了一百万次,但没有一个问题给出了符合POSIX标准的方法。

我需要获取计算机的本地网络地址,不使用 getifaddrs 或其他非POSIX兼容的接口方式。这是否可能?


2
如果您正在使用套接字与远程主机通信,则getsockname()应为此套接字提供本地地址。 - Ambroz Bizjak
2
没有所谓的本地网络地址。几乎每个启用了网络功能的计算机系统都有一个回环适配器(本地主机,通常是127.0.0.1::1,但也可能是其他值),以及一个或多个实际的网络接口,每个接口都有一个或多个IPv4和IPv6地址(或其他协议)。如果您只想处理一个地址,您要么需要使用一些启发式方法选择其中一个,要么让用户决定她想要使用哪个地址。 - Holger Just
如果你是root... system("ifconfig eth1 | grep 'inet addr' | cut -d ':' -f 2 | cut -d ' ' -f 1") 或者 popen() - pmg
1
pmg:ifconfig 在哪些方面符合 POSIX 标准? - raph.amiard
@pmg 尽管ifconfig非常标准并且是当前最好的方法,但一些Linux发行版如今开始不再提供ifconfig, 而只提供iproute2. 个人而言,我会选择SIOCGIFCONF - cnicutar
@HolgerJust:我知道没有唯一的本地网络地址这个事实。不过这并没有回答我的问题。如果我能得到其中任何一个,那就可以了。看来我做不到。 - raph.amiard
5个回答

7

虽然没有直接支持此事的选项,但您可以使用UDP套接字(SOCK_DGRAM)将其连接到已知的远程地址。由于UDP套接字是无状态的,因此不会产生任何网络流量。

然后,您可以查询该套接字的本地端点(getsockname)以获取通过您的系统路由的本地IP地址。同样,由于UDP是无状态的,因此这只是查询您的本地路由表,不产生任何真正的网络流量。

在此之后别忘了关闭套接字。

远程公共名称服务器非常适合此目的。您可以测试它们的几种可能性:

  • 其中一个偶尔可能会停机,或者由于某些原因无法到达该地区
  • 您的进程可能与服务器位于同一局域网中,并且您可能只获得一些特殊的本地地址
  • 测试IPv4和IPv6地址

为什么一个地址不可用很重要吗?反正路由应该一直存在。顺便说一下,8.8.8.8是一个容易记住的地址。 - R.. GitHub STOP HELPING ICE
1
@R..,谷歌的名称服务器是一个可能的选择。我添加了更多原因,为什么检查几个服务器可能是合适的。请查看我的编辑。 - Jens Gustedt

3

不,这是不可能的,因为posix没有指定访问该信息的API。

Unix通常支持getifaddrs或SIOCGIFCONF ioctl,因此请使用其中之一或其他系统相关API。请注意,一台机器上可能有(并且通常有)多个网络接口,您需要确定您感兴趣的接口。


+1 但是我想知道是否有一个好用的小库可以将其抽象出来。尽管(在我相对较少的经验中)我还没有遇到过没有 SIOCGIFCONF 的 Unix。 - cnicutar
感谢您的回答。这不是为了任何真实的编程,否则我已经使用getifaddrs了。这是为了一个作业,我只能使用符合POSIX标准的调用。我猜我的老师没有检查他要求的是否可能。 - raph.amiard
答案不正确。确实没有直接的API,但有其他方法可以实现。请查看我的回答。 - Jens Gustedt

-1

POSIX没有“网络”的概念,更不用说IP了。所以不行。

此外,一台机器可以有很多网络地址(至少回环地址,每个网络卡至少一个或多个IPv6地址等),“网络地址”也没有明确定义。


这就是为什么你应该将一个UDP套接字“连接”到给定的<addr>。操作系统会选择正确的接口来路由<addr>,而“getsockname”将获取所选接口的源IP。 - Grandswiss

-1
相当简单,当然:
#include <unistd.h>

int main(int argc, char* argv[]) {
  return 8 == write(1, "0.0.0.0\n", 8) ? 0 : 1;
}

-2
#include <stdio.h>

int main(int argc, char* argv[]) {
   printf("127.0.0.1\n");
}

@Jens:环回地址是一个完全有效的本地网络地址。 - Lightness Races in Orbit
2
你的回答对于提问者并没有真正帮助。有人甚至可能会认为你在嘲笑他,尽管他的问题是一个有效且有趣的问题。从技术上讲,只有在检查环回是否配置时,你的答案才是正确的。此外,它也可以设置为任何其他127地址,127.0.0.0是一个A类网络。只有对于IPv6,::1才始终是一个有效的地址。 - Jens Gustedt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接