getaddrinfo(查找服务器地址)
getaddrinfo()函数用于将一个服务的基本地址转换为一个元组列表,其中包含建立一个连接所需要的全部信息。比如其网络簇与协议等,示例如下:
import socket # 获取匹配开头字符串的所有属性值 def getConstants(prefix): return { getattr(socket, n): n for n in dir(socket) if n.startswith(prefix) } ipproto_str = getConstants("IPPROTO_") family_str = getConstants("AF_") type_str = getConstants("SOCK_") for response in socket.getaddrinfo('www.csdn.net', 'http', family=socket.AF_INET, type=socket.SOCK_STREAM, proto=socket.IPPROTO_TCP, flags=socket.AI_CANONNAME): family, socktype, ipproto, canonname, sockaddr = response print("地址簇: ", family_str[family]) print("套接字类型: ", type_str[socktype]) print("协议码: ", ipproto_str[ipproto]) print("主机规范名: ", canonname) print("ip地址与端口号:", sockaddr)
运行之后,效果如下:
这里如果只用socket.getaddrinfo(‘www.csdn.net’, ‘http’),表示不需要过滤任何连接信息,但大型的网站一般都有几个IP或者域名跳转到主页的。
所以通过后面的参数,可以筛选自己需要的链接信息。
其中,最后一个参数socket.AI_CANONNAME表示如果主机有别名,那么结果中会包含服务器的标准名。所有没有这个标志,标准名为空。
IP地址的表示方式
如果读者有C的经验,那么肯定知道,通过C语言编写的套接字程序是使用struct sockaddr结构体,它将IP地址表示为二进制,而不是上面显示的Python字符串形式。
如果想在Python和C之间转换IPv4地址,可以使用inet_aton()和inet_ntoa()。示例如下:
import socket import binascii ip_list = [ "192.168.50.1", "127.0.0.1" ] for ip in ip_list: packed = socket.inet_aton(ip) print("原始字符串ip地址:", ip) print("C库能识别的ip地址", binascii.hexlify(packed)) print("还原C库ip地址字符串", socket.inet_ntoa(packed)) print()
运行之后,效果如下:
inet_pton()与inet_ntop()
相信读者如果在测试上面代码,那么输入上面inet_aton()函数时,一定看到提醒中还有inet_pton()与inet_ntop()函数。
这2个函数既能处理IPv4也能处理IPv6,而inet_aton()和inet_ntoa()只能处理IPv4。它们的使用方式如下:
import socket import binascii ipv6_str = "2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b" packed = socket.inet_pton(socket.AF_INET6, ipv6_str) print("原始字符串ip地址:", ipv6_str) print("C库能识别的ip地址", binascii.hexlify(packed)) print("还原C库ip地址字符串", socket.inet_ntop(socket.AF_INET6, packed)) print() ipv4_str = "192.168.50.1" packed = socket.inet_pton(socket.AF_INET, ipv4_str) print("原始字符串ip地址:", ipv4_str) print("C库能识别的ip地址", binascii.hexlify(packed)) print("还原C库ip地址字符串", socket.inet_ntop(socket.AF_INET, packed)) print()
运行之后,效果如下: