如何在没有互联网连接、没有 eth0 且没有使用 C 的任何硬编码常量的情况下获取我的外部 IP(主接口)[关闭]

Posted

技术标签:

【中文标题】如何在没有互联网连接、没有 eth0 且没有使用 C 的任何硬编码常量的情况下获取我的外部 IP(主接口)[关闭]【英文标题】:How to get my external ip (primary interface) without internet connection, without eth0 and without any hardcoded constnts using C [closed] 【发布时间】:2018-01-04 18:51:27 【问题描述】:

大多数示例使用例如互联网连接 例如谷歌 dns。这是不同的坏方法,因为如果没有本地网络中的互联网,这将无法工作。

还有一些例子使用了不好的方法,比如分析 "eth0"。这是非常糟糕的方式来拥有这样的硬编码字符串。例如。在我的电脑中这不起作用,因为我的适配器名称是“ens160”而不是“eth0”:

ens160    Link encap:Ethernet  HWaddr 00:50:56:ba:75:ea  
          inet addr:192.168.0.237  Bcast:192.168.1.255  Mask:255.255.254.0
          inet6 addr: ... Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:205280 errors:0 dropped:1 overruns:0 frame:0
          TX packets:68958 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:266539618 (266.5 MB)  TX bytes:4771936 (4.7 MB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:825 errors:0 dropped:0 overruns:0 frame:0
          TX packets:825 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:74843 (74.8 KB)  TX bytes:74843 (74.8 KB)

我在本地网络的地址是“192.168.0.237”,这是ens160。这是在某些库创建套接字(例如 microhttpd 或任何其他)时在系统中使用的默认接口和 IP。如何使用标准 linux 库/函数检索它?

提前谢谢你

【问题讨论】:

是的。对不起。我的拼写错误。发布,星期五,工作日结束,头脑发热。 我需要做 X 我该怎么做 = 太宽泛了。 到底什么是默认界面?你为什么需要它?获取不是环回的接口——如果有多个接口,你会选择哪一个? 什么是“主界面”?一台机器可以有多个外部网络接口。 如果您的路由表有一条通过某个网关和某个接口的默认路由,请检查该接口的所有 IP 地址以找到与网关在同一子网中的那个。 【参考方案1】:

如果您只想发现默认适配器分配的 IP 地址,例如192.168.0.237,调用getifaddrs 并枚举每个地址。这与ifconfig 通常会显示与网关和网络掩码相关信息的适配器列表相同。过滤掉标记为IFF_LOOPBACK 或没有IFF_UP 的那些。一些示例代码here。

如果你有多个这样的地址,那么你需要检查路由表并找到默认路由(目标IP地址为0.0.0.0的那个)。

jselbie@ubuntu:~$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.254.2   0.0.0.0         UG    100    0        0 ens33
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 ens33
192.168.254.0   0.0.0.0         255.255.255.0   U     100    0        0 ens33

第一个条目,即目标路由为0.0.0.0 的条目是您的默认路由,并通过ens33 适配器发送。如果有多个默认路由,您将使用具有较低 metric 字段的那个。在我的例子中,0.0.0.0 路由的接口是ens33。如上所述,ens33 的 IP 地址可以通过调用getifaddrs 来发现。 (引用 ifaddrs 枚举列表中的ifa_name 字段。)

至于在 C 中以编程方式枚举路由表,我实际上不记得如何做到这一点。快速的互联网搜索表明您可以使用NETLINK 套接字。我也会参考路由命令的源代码。

【讨论】:

非常感谢。谢谢你。您的枚举方式和过滤(IFF_LOOPBACK + IFF_UP)建议确实有效。 只是一个小小的说明。您确定列表中的第一个不是环回和升级的适配器将是主要的(如果您写的是一个地址)?抱歉,我不是 linux 方面的专家。 不,我不相信您不能假设枚举的第一个适配器是托管默认路由的适配器。如果您有多个具有 IP 地址的活动适配器,则需要使用路由表查找 0.0.0.0 的路由。 感谢您的解释。现在我通过定义外部 IP 来理解这个问题。当您使用典型的 TCP 套接字(AF_INET,SOCK_STREAM,0)定义传出接口和 IP 地址时,似乎 TCP/IP 驱动程序会执行类似的操作。 @AlexanderSymonenko - 你是对的。当connect 被调用时,TCP/IP 参考路由表来决定通过哪个适配器建立连接。

以上是关于如何在没有互联网连接、没有 eth0 且没有使用 C 的任何硬编码常量的情况下获取我的外部 IP(主接口)[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Ionic 2 - 如果没有互联网 + 有效表单,我如何禁用按钮

为啥我的linux中没有eth0而是enpls0

ubuntu里终端中eth0为啥没有显示IP地址

如何在没有互联网连接的情况下持续显示警报?

如何在没有互联网的情况下从多个设备到单个设备进行通信[关闭]

虚拟机上RedHat网络不通,eth0没有ip