【发布时间】:2010-10-30 12:04:32
【问题描述】:
如何检索网络设备的网络掩码(最好在 Linux 中,但如果它是跨平台的,那就太棒了)?我知道如何在 Linux 上使用 C,但我在 Python 中找不到方法——也许减去 ctypes。那或解析ifconfig。还有什么办法吗?
ioctl(socknr, SIOCGIFNETMASK, &ifreq) // C version
【问题讨论】:
标签: python
如何检索网络设备的网络掩码(最好在 Linux 中,但如果它是跨平台的,那就太棒了)?我知道如何在 Linux 上使用 C,但我在 Python 中找不到方法——也许减去 ctypes。那或解析ifconfig。还有什么办法吗?
ioctl(socknr, SIOCGIFNETMASK, &ifreq) // C version
【问题讨论】:
标签: python
This 在 Linux 上的 Python 2.2 中为我工作:
iface = "eth0"
socket.inet_ntoa(fcntl.ioctl(socket.socket(socket.AF_INET, socket.SOCK_DGRAM), 35099, struct.pack('256s', iface))[20:24])
【讨论】:
netifaces 模块在这里值得一提。直接来自文档:
>>> netifaces.interfaces()
['lo0', 'gif0', 'stf0', 'en0', 'en1', 'fw0']
>>> addrs = netifaces.ifaddresses('en0')
>>> addrs[netifaces.AF_INET]
[{'broadcast': '10.15.255.255', 'netmask': '255.240.0.0', 'addr': '10.0.1.4'}, {'broadcast': '192.168.0.255', 'addr': '192.168.0.47'}]
适用于 Windows、Linux、OS X 和可能的其他 UNIX。
【讨论】:
你看过这里吗?
http://docs.python.org/library/fcntl.html
这适用于我在 Linux 上的 python 2.5.2 中。 Ben 领先时正在完成它,但它仍然在这里(可悲的是浪费了努力:-)):
vinko@parrot:~$ more get_netmask.py
# get_netmask.py by Vinko Vrsalovic 2009
# Inspired by http://code.activestate.com/recipes/439093/
# and http://code.activestate.com/recipes/439094/
# Code: 0x891b SIOCGIFNETMASK
import socket
import fcntl
import struct
import sys
def get_netmask(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x891b, struct.pack('256
s',ifname))[20:24])
if len(sys.argv) == 2:
print get_netmask(sys.argv[1])
vinko@parrot:~$ python get_netmask.py lo
255.0.0.0
vinko@parrot:~$ python get_netmask.py eth0
255.255.255.0
【讨论】:
您可以使用此库:http://github.com/rlisagor/pynetlinux。注意:我是图书馆的作者。
【讨论】:
我的想法是依靠子进程使用简单的 ifconfig (Linux) 或 ipconfig (windows) 请求来检索信息(如果 ip 已知)。 欢迎评论:
Windows
ip = '192.168.1.10' #Example
proc = subprocess.Popen('ipconfig',stdout=subprocess.PIPE)
while True:
line = proc.stdout.readline()
if ip.encode() in line:
break
mask = proc.stdout.readline().rstrip().split(b':')[-1].replace(b' ',b'').decode()
类 UNIX
ip = '192.168.1.10' #Example
proc = subprocess.Popen('ifconfig',stdout=subprocess.PIPE)
while True:
line = proc.stdout.readline()
if ip.encode() in line:
break
mask = line.rstrip().split(b':')[-1].replace(b' ',b'').decode()
使用与网络的套接字连接并使用getsockname()[0] 检索IP
【讨论】:
ifconfig 不再总是预先安装在 linux 上,新命令是 ip addr
在 Windows 中,这段代码可能有用:
import os
import sys
import _winreg
def main():
adapter_list_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards')
adapter_count = _winreg.QueryInfoKey(adapter_list_key)[0]
for i in xrange(adapter_count):
sub_key_name = _winreg.EnumKey(adapter_list_key, i)
adapter_key = _winreg.OpenKey(adapter_list_key, sub_key_name)
(adapter_service_name, _) = _winreg.QueryValueEx(adapter_key, "ServiceName")
(description, _) = _winreg.QueryValueEx(adapter_key, "Description")
adapter_registry_path = os.path.join(r'SYSTEM\ControlSet001\Services',
adapter_service_name, "Parameters", "Tcpip")
adapter_service_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
adapter_registry_path)
(subnet_mask, _) = _winreg.QueryValueEx(adapter_service_key, "SubnetMask")
(ip_address, _) = _winreg.QueryValueEx(adapter_service_key, "IpAddress")
sys.stdout.write("Name: %s\n" % adapter_service_name)
sys.stdout.write("Description: %s\n" % description)
sys.stdout.write("SubnetMask: %s\n" % subnet_mask)
sys.stdout.write("IpAdress: %s\n" % ip_address)
if __name__ == "__main__":
main()
从HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards 注册表项中获取网络适配器列表,然后从HKLM\SYSTEM\ControlSet001\Services\{adapter_guid}\Parameters\Tcpip 项中提取有关每个适配器的更多信息。
我在带有 2 个虚拟适配器的 Windows XP 上对其进行了测试,它运行良好。应该可以在 2000、2003 和 Vista 中使用。
【讨论】:
CurrentControlSet。我复制了一份here,因为它太长了,无法发表评论。
使用python pyroute2库可以获取所有网元属性:
from pyroute2 import IPRoute
ip = IPRoute()
info = [{'iface': x['index'], 'addr': x.get_attr('IFA_ADDRESS'), 'mask': x['prefixlen']} for x in ip.get_addr()]
【讨论】:
我将原始答案作为原始代码进行了更新:
struct.pack('256s', iface)
在 Python 3.9 中抛出错误,所以这里是一个重新审视的版本:
SIOCGIFADDR = 0x8915
def get_iface_ip(iface: str):
"""
Get network interface IP using the network interface name
:param iface: Interface name (like eth0, enp2s0, etc.)
:return IP address in the form XX.XX.XX.XX
"""
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
iface_bin = struct.pack('256s', bytes(iface, 'utf-8'))
packet_ip = fcntl.ioctl(s.fileno(), SIOCGIFADDR, iface_bin)[20:24]
return socket.inet_ntoa(packet_ip)
【讨论】:
您可以通过在 CMD 上运行命令并提取相关信息来实现此目的。
我的实现:
import subprocess
p = subprocess.Popen('ipconfig', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
if b'Subnet Mask' in line:
print(line.decode().split(' ')[-1].strip('\r\n'))
【讨论】:
来自文档
ipaddress 提供在 IPv4 和 IPv6 地址和网络上创建、操作和操作的功能。
此模块中的函数和类可以直接处理与 IP 地址相关的各种任务 ...
>>> import socket
>>> import ipaddress
>>>
>>> ip_addr = socket.gethostbyname(socket.gethostname())
>>> netmask = ipaddress.IPv4Network(ip_addr).netmask
>>> print(netmask)
255.255.255.255
>>> ...
这个问题可以回答here。这不是同一个问题,但也为您的问题提供了解决方案。
【讨论】:
If no mask is provided, it’s considered to be /32." 并且gethostbyname 从不附加子网前缀长度。所以你总是会得到255.255.255.255。模块ipaddress是一个纯计算库,不会从系统中查找缺失的信息。