Python网络编程学习笔记(三)——套接字名与DNS

代码清单4-1 使用getaddrinfo()创建并连接套接字

import argparse, socket, sys

def connect_to(hostname_or_ip):
    try:
        infolist = socket.getaddrinfo(hostname_or_ip, 'www', 0, socket.SOCK_STREAM, 0, socket.AI_ADDRCONFIG | socket.AI_V4MAPPED | socket.AI_CANONNAME)
        # getaddrinfo()请求连接到hostname_or_ip提供的HTTP服务所需的可能方法,返回一个可以提供链接的方法
        # AI_ADDRCONFIG标记,把计算机无法连接的所有地址过滤掉
        # AI_V4MAPPED,将IPv4地址重新编码为可实际使用的IPv6地址
        # AI_CANNONNAME,反向查询,返回元组的第四项中包含规范主机名
    except socket.gaierror as e:
        print('Name service failure:', e.args[1])
        sys.exit(1)
    
    info = infolist[0]          # 返回元组列表中第一项
    socket_args = info[0:3]     # 协议族
    address = info[4]           # 规范主机名
    s = socket.socket(*socket_args)
    try:
        s.connect(address)
    except socket.error as e:
        print('Network failure:', e.args[1])
    else:
        print('Success: host', info[3], ' is listening on port 80.')

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description = 'Try connecting to port 80')
    parser.add_argument('hostname', help='hostname that you want to contact')
    connect_to(parser.parse_args().hostname)

  getaddrinfo()函数用来将用户指定的主机名和端口号转换为可供套接字方法使用的地址所需要的重要方法。例如,使用getaddrinfo()获取baidu.com提供HTTP服务的方法:

import socket
infolist = socket.getaddrinfo('baidu.com','www')
infolist

  返回结果

[(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 0, '', ('111.13.101.208', 80)), 
(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 0, '', ('123.125.114.144', 80)), 
(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 0, '', ('220.181.57.217', 80))]

  从返回结果可以看出,提供3中方法连接baidu.com的HTTP服务,协议族为AF_INET(协议代号为2),数据报类型SOCK_STREAM(协议代号为1),第三项为0表示通配符(?),第四项为规范主机名,之后是IP地址和端口号的二元组。

  程序没有为socket函数传入三个独立的参数,而是使用星号传入列表,表示将socket_args表中的3个元素作为三个参数传入到构造函数中。

posted @ 2017-11-20 19:14  Wildgoose  阅读(370)  评论(0编辑  收藏  举报