ip地址由4段整数构成,每段范围从0到255,本文研究如何判断一个ip地址是否合法
socket.getaddrinfo方法的原型是
def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
该方法返回由元组组成的列表,下面的代码使用该方法获取百度域名的信息
import socket
print(socket.getaddrinfo('www.baidu.com', None))
程序输出结果
[(2, 1, 6, '', ('220.181.38.150', 0)), (2, 2, 17, '', ('220.181.38.150', 0)), (2, 3, 0, '', ('220.181.38.150', 0)), (2, 1, 6, '', ('220.181.38.149', 0)), (2, 2, 17, '', ('220.181.38.149', 0)), (2, 3, 0, '', ('220.181.38.149', 0))]
host既可以是域名,也可以是ip地址,如果方法能正常返回列表,则说明地址合法,反之地址不合法,在tornado源码里,有一个is_valid_ip函数就是利用该放方法进行判断
import socket
def is_valid_ip(ip):
"""Returns true if the given string is a well-formed IP address.
Supports IPv4 and IPv6.
"""
if not ip or '\x00' in ip:
# getaddrinfo resolves empty strings to localhost, and truncates
# on zero bytes.
return False
try:
res = socket.getaddrinfo(ip, 0, socket.AF_UNSPEC,
socket.SOCK_STREAM,
0, socket.AI_NUMERICHOST)
return bool(res)
except socket.gaierror as e:
if e.args[0] == socket.EAI_NONAME:
return False
raise
print(is_valid_ip('192.168.0.1'))
print(is_valid_ip('1.1.1'))
令人感到诧异的是,1.1.1被识别为正常的ip,原来它会被理解为1.1.0.1。
一个ip地址可以转换为int类型数据存储,这也是很多系统里喜欢使用的方法,相比于存储一个int类型数据,存储字符串ip占用的空间更多
import socket
import struct
ip = '127.0.0.1'
# 字符串ip转int类型
int_ip = socket.ntohl(struct.unpack("I",socket.inet_aton(str(ip)))[0])
print(int_ip)
# int类型ip转字符串ip
str_ip = socket.inet_ntoa(struct.pack('I',socket.htonl(int_ip)))
print(str_ip)
程序输出结果
2130706433
127.0.0.1
如果字符串ip是非法的,那么在转int类型ip时一定会发生异常,只需要捕捉到这个异常就可以断定ip是非法的
import socket
import struct
def is_valid_ip(ip):
try:
socket.ntohl(struct.unpack("I",socket.inet_aton(str(ip)))[0])
except OSError:
return False
return True
print(is_valid_ip('192.168.0.1')) # True
print(is_valid_ip('192.168.333.1')) # False
QQ交流群: 211426309