我正在用 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 等)。运行时配置将使系统管理员的工作更轻松!