# !/usr/bin/python3
# coding: utf-8
import os
import random
import sys
import IPy
import certifi
import netifaces
import pycurl
def list_ipv4_adapter():
mapping = {}
gateways = netifaces.gateways()
if netifaces.AF_INET in gateways:
ipv4gates = gateways[netifaces.AF_INET]
for gate in ipv4gates:
mac = gate[1][1:-1]
mapping[mac] = gate[0]
ipv4list = []
macs = netifaces.interfaces()
for mac in macs:
adapter = netifaces.ifaddresses(mac)
if netifaces.AF_INET not in adapter:
continue
ipv4group = adapter[netifaces.AF_INET]
if len(ipv4group) < 1:
# IPv4 is not enabled or configured
continue
# len(ipv4group) > 1
# One available network adapter is configured with multiple network segments
mac = mac[1:-1]
for ipv4 in ipv4group:
ip = ipv4['addr']
mask = ipv4['netmask']
# `broadcast` may be the upper limit address of this network segment
gate = mapping[mac] if mac in mapping else ipv4['broadcast']
ipv4list.append((ip, mask, gate, mac))
# [('127.0.0.1', '255.0.0.0', '127.255.255.255', 'DFCA0DEC-A7BA-11EB-A168-806E6F6E6963')]
return ipv4list
def is_adapter_up(ip):
"""
ip like 127.0.0.1
"""
if 'win32' == sys.platform:
cmd = 'ipconfig |findstr "%s"'
# Using `ipconfig -all` to show all, includes not running
elif 'linux' == sys.platform:
cmd = 'ifconfig |grep "%s"'
# Using `ifconfig -a` to show all, includes not running
# Using `ifconfig NAME up` to start
# Using `ifconfig NAME down` to close
else:
print('Unsupported system type %s' % sys.platform)
return False
with os.popen(cmd % ip, 'r') as f:
if '' != f.read():
# UP and RUNNING
return True
else:
print('Network adapter %s is not running' % ip)
return False
def in_same_segment(ip, mask, addr):
"""
ip like 127.0.0.1
mask like 255.0.0.0
addr like 192.168.1.1
"""
# Specifies whether the address is in the network segment
if '' == addr.strip():
return True
subnet = IPy.IP('%s/%s' % (ip, mask), make_net=True)
if addr not in subnet:
print('Address %s is not in the segment of %s' % (addr, subnet))
return False
return True
def usable_ipv4_adapter(ipv4list, addr=''):
"""
ipv4list like [('127.0.0.1', '255.0.0.0', '127.255.255.255', 'DFCA0DEC-A7BA-11EB-A168-806E6F6E6963')]
addr like 192.168.1.1
"""
if '' != addr.strip():
iterator = filter(lambda item: in_same_segment(item[0], item[1], addr), ipv4list)
ipv4list = list(iterator)
if len(ipv4list) < 1:
return []
iterator = filter(lambda item: is_adapter_up(item[0]), ipv4list)
return list(iterator)
def ping_to_website(website, interface):
"""
website like https://www.baidu.com/
interface like 127.0.0.1
"""
c = pycurl.Curl()
try:
c.setopt(pycurl.URL, website)
c.setopt(pycurl.CAINFO, certifi.where()) # for https, also supported HTTP
c.setopt(pycurl.USERAGENT, "Chrome/91.0.4472.77")
c.setopt(pycurl.FOLLOWLOCATION, 1)
c.setopt(pycurl.MAXREDIRS, 5)
c.setopt(pycurl.CONNECTTIMEOUT, 1)
c.setopt(pycurl.TIMEOUT, 1) # too strict
if interface:
c.setopt(pycurl.INTERFACE, interface)
c.setopt(pycurl.WRITEFUNCTION, lambda i: None) # avoid print too much
c.perform() # default to print HTML content
code = c.getinfo(pycurl.HTTP_CODE)
if 200 == code:
return True
return False
except pycurl.error as e:
return False
finally:
if c:
c.close()
def ping_to_internet(interface):
"""
interface like 127.0.0.1
"""
websites = ['https://www.baidu.com/', 'https://www.google.com.hk/']
for website in websites:
if ping_to_website(website, interface):
print('Network adapter %s can connect to the Internet' % interface)
return True
return False
def internet_ok_adapter(ipv4list):
"""
ipv4list like [('127.0.0.1', '255.0.0.0', '127.255.255.255', 'DFCA0DEC-A7BA-11EB-A168-806E6F6E6963')]
"""
iterator = filter(lambda item: ping_to_internet(item[0]), ipv4list)
return list(iterator)
def local(addr='', internet=False):
"""
addr like 192.168.1.1
internet is boolean
"""
print()
# The available local IP address in the same network segment as the specified web address
ipv4adapters = list_ipv4_adapter()
if len(ipv4adapters) < 1:
print('0 IPv4 network adapter were found')
return ''
print('%s IPv4 network adapter were found:' % len(ipv4adapters))
for i, adapter in enumerate(ipv4adapters):
print(
' [%s] IP: %s, NetMask: %s, GateWay: %s, MAC: %s' % (i + 1, adapter[0], adapter[1], adapter[2], adapter[3]))
ipv4adapters = usable_ipv4_adapter(ipv4adapters, addr)
if len(ipv4adapters) < 1:
print('0 IPv4 network adapter are unavailable')
return ''
if internet:
ipv4adapters = internet_ok_adapter(ipv4adapters)
if len(ipv4adapters) < 1:
print('0 IPv4 network adapter able to connect Internet')
return ''
if len(ipv4adapters) == 1:
ip, mask, gate, mac = ipv4adapters[0]
print('Only one network adapter is qualified:')
else:
# 1. Multiple network adapter available
# Network segments between adapters cannot overlap
# 2. One available network adapter is configured with multiple network segments
# Network segments of the same adapter can overlap
ip, mask, gate, mac = random.choice(ipv4adapters)
print('Multiple network adapter are available, randomly select one:')
print(' IP: %s, NetMask: %s, GateWay: %s, MAC: %s' % (ip, mask, gate, mac))
return ip
def access(port):
if port < 1024 or 65535 < port:
# privileged port
# out of range
return False
if 'win32' == sys.platform:
cmd = 'netstat -aon|findstr ":%s "' % port
elif 'linux' == sys.platform:
cmd = 'netstat -aon|grep ":%s "' % port
else:
print('Unsupported system type %s' % sys.platform)
return False
with os.popen(cmd, 'r') as f:
if '' != f.read():
print('Port %s is occupied' % port)
return False
else:
return True
if __name__ == "__main__":
print('The IP address of this device is %s' % local('', True))
print('The IP address of this device is %s' % local('172.17.0.1', False))
一次执行输出示例:
4 IPv4 network adapter were found:
[1] IP: 172.17.0.1, NetMask: 0.0.0.0, GateWay: 255.255.255.255, MAC: 12A34BCD-5EFG-6789-H0IG-12K34LM567N8
[2] IP: 10.20.30.40, NetMask: 255.255.255.255, GateWay: 10.20.30.40, MAC: 901234O5-PQ67-8901-R23S-456T7U89VW01
[3] IP: 192.168.1.1, NetMask: 255.255.255.255, GateWay: 192.168.1.254, MAC: X23YZ4AB-56CD-7890-1E23-45F6GHIJ7890
[4] IP: 127.0.0.1, NetMask: 255.0.0.0, GateWay: 127.255.255.255, MAC: KLMN1OPQ-R2ST-34UV-W567-890X1Y2Z3456
Network adapter 127.0.0.1 is not running
Network adapter 172.17.0.1 can connect to the Internet
Network adapter 192.168.1.1 can connect to the Internet
Multiple network adapter are available, randomly select one:
IP: 192.168.1.1, NetMask: 255.255.255.255, GateWay: 192.168.1.254, MAC: X23YZ4AB-56CD-7890-1E23-45F6GHIJ7890
The IP address of this device is 192.168.1.1
4 IPv4 network adapter were found:
[1] IP: 172.17.0.1, NetMask: 0.0.0.0, GateWay: 255.255.255.255, MAC: 12A34BCD-5EFG-6789-H0IG-12K34LM567N8
[2] IP: 10.20.30.40, NetMask: 255.255.255.255, GateWay: 10.20.30.40, MAC: 901234O5-PQ67-8901-R23S-456T7U89VW01
[3] IP: 192.168.1.1, NetMask: 255.255.255.255, GateWay: 192.168.1.254, MAC: X23YZ4AB-56CD-7890-1E23-45F6GHIJ7890
[4] IP: 127.0.0.1, NetMask: 255.0.0.0, GateWay: 127.255.255.255, MAC: KLMN1OPQ-R2ST-34UV-W567-890X1Y2Z3456
Address 172.17.0.1 is not in the segment of 10.20.30.40
Address 172.17.0.1 is not in the segment of 192.168.1.1
Address 172.17.0.1 is not in the segment of 127.0.0.1
Only one network adapter is qualified:
IP: 172.17.0.1, NetMask: 0.0.0.0, GateWay: 255.255.255.255, MAC: 12A34BCD-5EFG-6789-H0IG-12K34LM567N8
The IP address of this device is 172.17.0.1