我有一个 python 类,它可以获取您所在的本地计算机的 IP 地址。它适用于实际硬件(除非是涉及桥接设备的 MacOS)或本地虚拟机。这是代码:
class IPAddress:
ip_address = None
def __init__(self):
return
def _get_interface_ip(self,ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s',
ifname[:15]))[20:24])
# does not work on MacOS with bridged devices such as vboxnet0, tap0, tun0
def get_lan_ip(self):
hostname = socket.gethostname()
ip = u''
try:
ip = socket.gethostbyname(hostname)
except socket.gaierror, e:
try:
ip = socket.gethostbyname(u'localhost')
except: pass
if ip.startswith("127.") and os.name != "nt":
interfaces = [
"eth0",
"eth1",
"eth2",
"en0",
"en1",
"en2",
"wlan0",
"wlan1",
"wifi0",
"ath0",
"ath1",
"ppp0",
]
for ifname in interfaces:
try:
ip = self._get_interface_ip(ifname)
break
except IOError:
pass
return ip
# Find out this instance
x = IPAddress()
server_ip = x.get_lan_ip()
除了 AWS 之外,这似乎在任何地方都适用。在 AWS 上,ifconfig eth0 提供分配给 eth0 的内部 IP 地址,而该类提供与访问实例关联的外部 CNAME IP 地址(在 EC2 Classic 中)。
什么给了?有没有更好的方法来进行 self 发现(例如)boto?
最佳答案
首先,我不会使用 gethostbyname()
或其同类。这样做依赖于您无法控制的外部数据库,而且这些数据库通常不是最新的。
接下来,我不会调用ioctl()
。任何特定 ioctl 的存在,更不用说其行为,都没有跨操作系统标准化。
如果是我,我会connect()
到一些外部服务,然后调用socket.getsockname()
:
def get_my_addr():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 53))
return s.getsockname()[0]
如果这不起作用,我会 connect()
到基于 TCP 的服务:
def get_my_addr():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('www.google.com', 80))
return s.getsockname()[0]
关于Python IP地址发现代码给出外部IP而不是eth0设备IP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24896141/