Việc dựa vào mô-đun "struct" có thể gây ra vấn đề với kích thước kiểu và kích thước endian-ness và chỉ là không cần thiết. Socket.inet_aton () cũng vậy. Python hoạt động rất tốt với các địa chỉ IP bốn chấm:
def ip_to_u32(ip):
return int(''.join('%02x' % int(d) for d in ip.split('.')), 16)
Tôi cần thực hiện đối sánh IP trên mỗi lệnh gọi accept () socket, với toàn bộ tập hợp các mạng nguồn được phép, vì vậy tôi tính toán trước mặt nạ và mạng, dưới dạng số nguyên:
SNS_SOURCES = [
# US-EAST-1
'207.171.167.101',
'207.171.167.25',
'207.171.167.26',
'207.171.172.6',
'54.239.98.0/24',
'54.240.217.16/29',
'54.240.217.8/29',
'54.240.217.64/28',
'54.240.217.80/29',
'72.21.196.64/29',
'72.21.198.64/29',
'72.21.198.72',
'72.21.217.0/24',
]
def build_masks():
masks = [ ]
for cidr in SNS_SOURCES:
if '/' in cidr:
netstr, bits = cidr.split('/')
mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
net = ip_to_u32(netstr) & mask
else:
mask = 0xffffffff
net = ip_to_u32(cidr)
masks.append((mask, net))
return masks
Sau đó, tôi có thể nhanh chóng xem liệu một IP nhất định có nằm trong một trong các mạng đó hay không:
ip = ip_to_u32(ipstr)
for mask, net in cached_masks:
if ip & mask == net:
# matched!
break
else:
raise BadClientIP(ipstr)
Không cần nhập mô-đun và mã khớp rất nhanh.