获取局域网 IP,一般做法是先枚举网卡、再获取 IP,但是这种做法的缺点是,不够便携,在不同的机器上需要不同的配置,代码实现上也比较啰嗦。这里搬运一段来自 Stack Overflow 的代码,适用性强、十分优雅。使用 Python 实现,我也就发在 Python 节点了,其他语言也可以借鉴。
import socket
def get_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# doesn't even have to be reachable
s.connect(('10.255.255.255', 1))
IP = s.getsockname()[0]
except Exception:
IP = '127.0.0.1'
finally:
s.close()
return IP
来源: networking - Finding local IP addresses using Python's stdlib - Stack Overflow
比如,DDNS 客户端,如果想要为局域网 IP 绑定域名,往往需要人工选择网卡或者正则表达式匹配域名,我见过的几个 DDNS 客户端比如 No-IP Dynamic Update Client、NewFuture/DDNS 都是这么做的,一般 DDNS 客户端则不支持使用局域网 IP 。如果使用上述代码或思路,就可以方便获取局域网 IP 、简化程序设计、简化用户配置。
1
proxytoworld 2021-10-19 21:41:21 +08:00
这是适用于 网卡和外头连接的,如果有几个网卡,那些网卡不和外界连接的话就没办法了,这个获取本机 IP 的实现在 mirai 木马里面有
|
2
starsky007 OP @proxytoworld
我看原帖里有提到“Works even if all interfaces are unplugged from the network”,即使没有外网连接,也能获取默认路由 IP 。 |
3
adoal 2021-10-19 22:04:44 +08:00
“不够便携”……机翻的?
|
4
starsky007 OP @adoal
只有代码是搬运的,其他是我自己写的。protable/便携,意思是,不同环境下只需要配置一次;表达可能有点生硬,您有什么建议? |
5
princelai 2021-10-19 22:33:03 +08:00 via Android
@starsky007 结合上下文,不能在别的机器上用,应该翻译成不便移植更好吧
|
6
chenqh 2021-10-19 23:58:43 +08:00 1
|
8
dingwen07 2021-10-20 00:25:58 +08:00 via iPhone
socket.gethostbyname(socket.gethostname())
|
9
dingwen07 2021-10-20 00:26:31 +08:00 via iPhone
#8 盲猜的,没试过
|
10
kokutou 2021-10-20 04:39:56 +08:00 via Android 4
局域网 IP❎
默认路由 IP✅ |
11
raysonx 2021-10-20 04:47:17 +08:00 via iPad
IPv4 only 的。。。。
|
12
skinny 2021-10-20 08:03:27 +08:00
10.255.255.255 换成任意 IP 结果也是一样的
|
13
starsky007 OP @princelai
“可移植”一般指的是二进制文件在不同操作系统平台上能运行。 |
14
starsky007 OP @chenqh
好问题。准确地说,代码不是获取局域网 IP,而是获取具有默认路由的本地 IP 。 |
15
starsky007 OP @dingwen07
原帖里其他回答也说了你说的这种写法,是不一样的。 |
16
starsky007 OP @kokutou
👍 |
17
starsky007 OP @skinny
原帖里说了为什么要用 10.255.255.255 ,有差别。 |
18
starsky007 OP 还是要看一下原帖,帖子只是搬运代码、加了一点点自己的评论,并没有把原帖里面的讨论全部翻译过来。
|
19
ungrown 2021-10-20 10:33:20 +08:00 1
@dangyuluo #7 咱也没必要转进到“信达雅”吧,再说“便携”其实挺信达雅的。
把 portable 这个词用来指代“轻便性”、“自适应性”、“可移植性”或者“自带运行环境无需额外安装”,本来就是类似于比喻的修辞用法,大家觉得这个词表达效果很精妙所以变成了常用语。 portable 的精髓就是讲究一个“随遇而安”,借用“便携”的表意来表达这份“随意性”、“轻便性”,倒并非刻意指代“移植”,所以直接按照字面意思来翻译就挺好。 |
20
ungrown 2021-10-20 10:37:53 +08:00
我觉得这个函数的局限性还是应该体现在这个帖子的标题当中的,那就是用它写回答的人所表达的那样:它只能获取到设备的“主”IP 地址(也就是附带默认路由的那个地址),而并不能列出所有网络接口上的地址。
|
21
Wincer 2021-10-20 10:42:07 +08:00
试试 psutil 这个库
|
22
starsky007 OP |
23
julyclyde 2021-10-20 12:16:24 +08:00
我们这里都是用 magic number 8915 的,嘿嘿
然后到 mac 上就不行了 |
24
exiaohao 2021-10-20 12:24:17 +08:00
这个面对大多数情况应该是够了吧,而且是挺巧妙的
但是如果对 10.255.255.255 这个地址 有什么策略路由或者走的网卡不一样可能会有不一样的结果?赶脚还能用来探测不同地址的不同路由 hh |
25
skinny 2021-10-20 13:37:40 +08:00
@starsky007 原帖说的是广播地址就可以,因为程序不能直接使用广播地址。并不是说一定要 10.255.255.255
|
26
ZeroDu 2021-10-21 09:57:11 +08:00
这个不错,在 java 里面怎么实现?
|
27
vanton 2021-11-09 15:52:28 +08:00
本地目录装个 psutil ,然后直接用 psutil.net_if_addrs() 不就得了。
|