Debian jessie 下使用 Python 的 stdlib 查找本地 IP 地址

Debian jessie 下使用 Python 的 stdlib 查找本地 IP 地址

我正在用 python 编写一个分布式系统程序,在这个程序中我需要知道本地 ip 地址...例如 168.192.... 10.13..... 等等,而不是 127.0.0.1 或主机名。

我在 stackoverflow 上找到了以下解决方案

https://stackoverflow.com/questions/166506/finding-local-ip-addresses-using-pythons-stdlib

import socket
socket.gethostbyname(socket.gethostname())

当我在 Debian jessie 笔记本电脑上运行此程序时,我得到了 127.0.0.1,然而我的朋友在他的机器上使用 Fedora,当他运行相同的脚本时会获得所需的 IP 地址(例如 168.192..)

如果可能的话,我更喜欢使用上面的解决方案来获取本地 IP 地址,因为大多数其他提出的解决方案要么是黑客攻击,要么是令人难以置信的长...

我可以在我的 Debian jessie 笔记本电脑上设置一些东西,以便 python 返回正确的本地 ip 地址?

  • 使用 Debian Jessie
  • 蟒蛇3
  • 已连接到网络(..并且计算机已打开)... ;)
  • /etc/hosts 当前包含:

127.0.0.1 localhost 127.0.0.1 debianASUS ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters

答案1

查找主机将用于通信的 IP 地址的最可靠方法是使用getsockname已连接的 UDP 套接字。对于 UDP,connect系统调用不涉及任何网络通信。

这是我以前为类似目的编写的一个 Python 函数。如果您事先不知道要与哪个远程 IP 地址通信,则应该寻找一个将使用默认路由的 IP 地址。如果您已经知道要与哪个远程 IP 地址通信,那么最好在 connect 调用中使用该 IP 地址。

def my_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        s.connect(('192.0.0.8', 1027))
    except socket.error:
        return None
    return s.getsockname()[0]

经过一些小的改动,这个函数可以返回 IPv6 地址而不是 IPv4 地址:

def my_ipv6():
    s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
    try:
        s.connect(('2001:db8::', 1027))
    except socket.error:
        return None
    return s.getsockname()[0]

答案2

您是否考虑过通过配置参数在运行时将决定权交给最终用户?这是解决此问题的标准做法。

原因是没有系统万无一失的方法来计算“本地” IP 地址(主机可能是多宿主的,可能正在运行 v4/v6 双栈、VPN 等)。运行时配置将使系统管理员的工作更轻松!

相关内容