V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
starsky007
V2EX  ›  Python

搬运一段 Python 获取局域网 IP 的方法,十分优雅!

  •  
  •   starsky007 · 45 天前 · 4057 次点击
    这是一个创建于 45 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码

    获取局域网 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 ClientNewFuture/DDNS 都是这么做的,一般 DDNS 客户端则不支持使用局域网 IP 。如果使用上述代码或思路,就可以方便获取局域网 IP 、简化程序设计、简化用户配置。

    27 条回复    2021-11-09 15:52:28 +08:00
    proxytoworld
        1
    proxytoworld  
       45 天前
    这是适用于 网卡和外头连接的,如果有几个网卡,那些网卡不和外界连接的话就没办法了,这个获取本机 IP 的实现在 mirai 木马里面有
    starsky007
        2
    starsky007  
    OP
       45 天前
    @proxytoworld
    我看原帖里有提到“Works even if all interfaces are unplugged from the network”,即使没有外网连接,也能获取默认路由 IP 。
    adoal
        3
    adoal  
       45 天前
    “不够便携”……机翻的?
    starsky007
        4
    starsky007  
    OP
       45 天前
    @adoal
    只有代码是搬运的,其他是我自己写的。protable/便携,意思是,不同环境下只需要配置一次;表达可能有点生硬,您有什么建议?
    princelai
        5
    princelai  
       45 天前 via Android
    @starsky007 结合上下文,不能在别的机器上用,应该翻译成不便移植更好吧
    chenqh
        6
    chenqh  
       45 天前   ❤️ 1
    这个东西好像不对,如果用了 vpn 的话

    PS D:\ccode\HelloWorld> & C:/Users/Lenovo/AppData/Local/Microsoft/WindowsApps/python3.8.exe d:/ccode/HelloWorld/local.py
    10.110.110.122
    PS D:\ccode\HelloWorld> & C:/Users/Lenovo/AppData/Local/Microsoft/WindowsApps/python3.8.exe d:/ccode/HelloWorld/local.py
    192.168.50.235
    dangyuluo
        7
    dangyuluo  
       45 天前
    @princelai 现在社会步伐这么快,谁有空来翻译地信雅达
    dingwen07
        8
    dingwen07  
       45 天前 via iPhone
    socket.gethostbyname(socket.gethostname())
    dingwen07
        9
    dingwen07  
       45 天前 via iPhone
    #8 盲猜的,没试过
    kokutou
        10
    kokutou  
       45 天前 via Android   ❤️ 4
    局域网 IP❎
    默认路由 IP✅
    raysonx
        11
    raysonx  
       45 天前 via iPad
    IPv4 only 的。。。。
    skinny
        12
    skinny  
       45 天前
    10.255.255.255 换成任意 IP 结果也是一样的
    starsky007
        13
    starsky007  
    OP
       45 天前
    @princelai
    “可移植”一般指的是二进制文件在不同操作系统平台上能运行。
    starsky007
        14
    starsky007  
    OP
       45 天前
    @chenqh
    好问题。准确地说,代码不是获取局域网 IP,而是获取具有默认路由的本地 IP 。
    starsky007
        15
    starsky007  
    OP
       45 天前
    @dingwen07
    原帖里其他回答也说了你说的这种写法,是不一样的。
    starsky007
        16
    starsky007  
    OP
       45 天前
    @kokutou
    👍
    starsky007
        17
    starsky007  
    OP
       45 天前
    @skinny
    原帖里说了为什么要用 10.255.255.255 ,有差别。
    starsky007
        18
    starsky007  
    OP
       45 天前
    还是要看一下原帖,帖子只是搬运代码、加了一点点自己的评论,并没有把原帖里面的讨论全部翻译过来。
    ungrown
        19
    ungrown  
       45 天前   ❤️ 1
    @dangyuluo #7 咱也没必要转进到“信达雅”吧,再说“便携”其实挺信达雅的。
    把 portable 这个词用来指代“轻便性”、“自适应性”、“可移植性”或者“自带运行环境无需额外安装”,本来就是类似于比喻的修辞用法,大家觉得这个词表达效果很精妙所以变成了常用语。
    portable 的精髓就是讲究一个“随遇而安”,借用“便携”的表意来表达这份“随意性”、“轻便性”,倒并非刻意指代“移植”,所以直接按照字面意思来翻译就挺好。
    ungrown
        20
    ungrown  
       45 天前
    我觉得这个函数的局限性还是应该体现在这个帖子的标题当中的,那就是用它写回答的人所表达的那样:它只能获取到设备的“主”IP 地址(也就是附带默认路由的那个地址),而并不能列出所有网络接口上的地址。
    Wincer
        21
    Wincer  
       45 天前
    试试 psutil 这个库
    starsky007
        22
    starsky007  
    OP
       45 天前
    @ungrown
    @Wincer
    需求不就是方便快捷地获取默认主 IP 吗?
    julyclyde
        23
    julyclyde  
       45 天前
    我们这里都是用 magic number 8915 的,嘿嘿
    然后到 mac 上就不行了
    exiaohao
        24
    exiaohao  
       45 天前
    这个面对大多数情况应该是够了吧,而且是挺巧妙的
    但是如果对 10.255.255.255 这个地址 有什么策略路由或者走的网卡不一样可能会有不一样的结果?赶脚还能用来探测不同地址的不同路由 hh
    skinny
        25
    skinny  
       44 天前
    @starsky007 原帖说的是广播地址就可以,因为程序不能直接使用广播地址。并不是说一定要 10.255.255.255
    ZeroDu
        26
    ZeroDu  
       44 天前
    这个不错,在 java 里面怎么实现?
    vanton
        27
    vanton  
       24 天前
    本地目录装个 psutil ,然后直接用 psutil.net_if_addrs() 不就得了。
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2209 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 05:28 · PVG 13:28 · LAX 21:28 · JFK 00:28
    ♥ Do have faith in what you're doing.