python判断ip地址是否合法

ip地址由4段整数构成,每段范围从0到255,本文研究如何判断一个ip地址是否合法

1. 使用socket.getaddrinfo

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。

2. 利用ip转整数

一个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

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案