|
|
|
@ -8,14 +8,15 @@ import socket
|
|
|
|
|
import ctypes
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 定义一个结构体,用于存储socket地址信息
|
|
|
|
|
class sockaddr(ctypes.Structure):
|
|
|
|
|
_fields_ = [("sa_family", ctypes.c_short),
|
|
|
|
|
("__pad1", ctypes.c_ushort),
|
|
|
|
|
("ipv4_addr", ctypes.c_byte * 4),
|
|
|
|
|
("ipv6_addr", ctypes.c_byte * 16),
|
|
|
|
|
("__pad2", ctypes.c_ulong)]
|
|
|
|
|
_fields_ = [("sa_family", ctypes.c_short), # 地址族(例如AF_INET或AF_INET6)
|
|
|
|
|
("__pad1", ctypes.c_ushort), # 填充字段
|
|
|
|
|
("ipv4_addr", ctypes.c_byte * 4), # IPv4地址(4个字节)
|
|
|
|
|
("ipv6_addr", ctypes.c_byte * 16),# IPv6地址(16个字节)
|
|
|
|
|
("__pad2", ctypes.c_ulong)] # 填充字段
|
|
|
|
|
|
|
|
|
|
# 根据操作系统的不同,导入不同的库
|
|
|
|
|
if hasattr(ctypes, 'windll'):
|
|
|
|
|
WSAStringToAddressA = ctypes.windll.ws2_32.WSAStringToAddressA
|
|
|
|
|
WSAAddressToStringA = ctypes.windll.ws2_32.WSAAddressToStringA
|
|
|
|
@ -27,12 +28,13 @@ else:
|
|
|
|
|
WSAStringToAddressA = not_windows
|
|
|
|
|
WSAAddressToStringA = not_windows
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# inet_pton函数:将IP字符串转换为二进制格式
|
|
|
|
|
def inet_pton(address_family, ip_string):
|
|
|
|
|
addr = sockaddr()
|
|
|
|
|
addr.sa_family = address_family
|
|
|
|
|
addr_size = ctypes.c_int(ctypes.sizeof(addr))
|
|
|
|
|
addr = sockaddr() # 创建sockaddr实例
|
|
|
|
|
addr.sa_family = address_family # 设置地址族
|
|
|
|
|
addr_size = ctypes.c_int(ctypes.sizeof(addr)) # 获取地址结构体大小
|
|
|
|
|
|
|
|
|
|
# 使用WSAStringToAddressA函数将IP字符串转换为地址结构体
|
|
|
|
|
if WSAStringToAddressA(
|
|
|
|
|
ip_string,
|
|
|
|
|
address_family,
|
|
|
|
@ -42,6 +44,7 @@ def inet_pton(address_family, ip_string):
|
|
|
|
|
) != 0:
|
|
|
|
|
raise socket.error(ctypes.FormatError())
|
|
|
|
|
|
|
|
|
|
# 根据地址族返回对应的二进制IP地址
|
|
|
|
|
if address_family == socket.AF_INET:
|
|
|
|
|
return ctypes.string_at(addr.ipv4_addr, 4)
|
|
|
|
|
if address_family == socket.AF_INET6:
|
|
|
|
@ -49,14 +52,15 @@ def inet_pton(address_family, ip_string):
|
|
|
|
|
|
|
|
|
|
raise socket.error('unknown address family')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# inet_ntop函数:将二进制格式的IP地址转换为字符串
|
|
|
|
|
def inet_ntop(address_family, packed_ip):
|
|
|
|
|
addr = sockaddr()
|
|
|
|
|
addr.sa_family = address_family
|
|
|
|
|
addr_size = ctypes.c_int(ctypes.sizeof(addr))
|
|
|
|
|
ip_string = ctypes.create_string_buffer(128)
|
|
|
|
|
ip_string_size = ctypes.c_int(ctypes.sizeof(ip_string))
|
|
|
|
|
addr = sockaddr() # 创建sockaddr实例
|
|
|
|
|
addr.sa_family = address_family # 设置地址族
|
|
|
|
|
addr_size = ctypes.c_int(ctypes.sizeof(addr)) # 获取地址结构体大小
|
|
|
|
|
ip_string = ctypes.create_string_buffer(128) # 创建字符串缓冲区
|
|
|
|
|
ip_string_size = ctypes.c_int(ctypes.sizeof(ip_string)) # 获取字符串缓冲区大小
|
|
|
|
|
|
|
|
|
|
# 根据地址族将二进制IP地址复制到地址结构体中
|
|
|
|
|
if address_family == socket.AF_INET:
|
|
|
|
|
if len(packed_ip) != ctypes.sizeof(addr.ipv4_addr):
|
|
|
|
|
raise socket.error('packed IP wrong length for inet_ntoa')
|
|
|
|
@ -68,6 +72,7 @@ def inet_ntop(address_family, packed_ip):
|
|
|
|
|
else:
|
|
|
|
|
raise socket.error('unknown address family')
|
|
|
|
|
|
|
|
|
|
# 使用WSAAddressToStringA函数将地址结构体转换为IP字符串
|
|
|
|
|
if WSAAddressToStringA(
|
|
|
|
|
ctypes.byref(addr),
|
|
|
|
|
addr_size,
|
|
|
|
@ -77,9 +82,10 @@ def inet_ntop(address_family, packed_ip):
|
|
|
|
|
) != 0:
|
|
|
|
|
raise socket.error(ctypes.FormatError())
|
|
|
|
|
|
|
|
|
|
# 返回IP字符串
|
|
|
|
|
return ip_string[:ip_string_size.value - 1]
|
|
|
|
|
|
|
|
|
|
# Adding our two functions to the socket library
|
|
|
|
|
# 如果当前操作系统是Windows,将自定义的inet_pton和inet_ntop函数添加到socket库中
|
|
|
|
|
if os.name == 'nt':
|
|
|
|
|
socket.inet_pton = inet_pton
|
|
|
|
|
socket.inet_ntop = inet_ntop
|
|
|
|
|
socket.inet_ntop = inet_ntop
|