IPv6、Unix 域套接字和网络接口

来源:互联网 发布:do as infinity 知乎 编辑:程序博客网 时间:2024/05/22 01:21

本文基于 《Python网络编程攻略》 第三章,使用 Python3 改写。
主要介绍以下内容:

  • Python 标准库中的 ayncore 异步模块
  • 网络数据包抓取库 Scapy
  • Python 中 IPv6 的处理方法

把本地端口转发到远程主机

有时,你需要创建一个本地端口转发器,把本地端口发送的流量全部重定向到特定的远程主机上。利用这个功能,可以让用户只能访问特定的网站,而不能访问其他网站。

#!/usr/bin/env python3# -*- coding: utf-8 -*-import argparseimport asyncoreimport socketLOCAL_SERVER_HOST = 'localhost'REMOTE_SERVER_HOST = 'news.baidu.com'BUFSIZE = 4096class PortForwarder(asyncore.dispatcher):    def __init__(self, ip, port, remoteip, remoteport, backlog = 5):        asyncore.dispatcher.__init__(self)        self.remoteip = remoteip        self.remoteport = remoteport        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)        self.set_reuse_addr()        self.bind((ip, port))        self.listen(backlog)    def handle_accept(self):        conn, addr = self.accept()        print('Connected to:', addr)        Sender(Receiver(conn), self.remoteip, self.remoteport)class Receiver(asyncore.dispatcher):    def __init__(self, conn):        asyncore.dispatcher.__init__(self, conn)        self.from_remote_buffer = b''        self.to_remote_buffer = b''        self.sender = None    def handle_connect(self):        pass    def handle_read(self):        read = self.recv(BUFSIZE)        self.from_remote_buffer += read    def writable(self):        return (len(self.to_remote_buffer) > 0)    def handle_write(self):        sent = self.send(self.to_remote_buffer)        self.to_remote_buffer = self.to_remote_buffer[sent:]    def handle_close(self):        self.close()        if self.sender:            self.sender.close()class Sender(asyncore.dispatcher):    def __init__(self, receiver, remoteaddr, remoteport):        asyncore.dispatcher.__init__(self)        self.receiver = receiver        receiver.sender = self        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)        self.connect((remoteaddr, remoteport))    def handle_connect(self):        pass    def handle_read(self):        read = self.recv(BUFSIZE)        self.receiver.to_remote_buffer += read    def wirtable(self):        return (len(self.self.receiver.from_remote_buffer) > 0)    def handle_write(self):        sent = self.send(self.receiver.from_remote_buffer)        self.receiver.from_remote_buffer = self.receiver.from_remote_buffer[sent:]    def handle_close(self):        self.close()        self.receiver.close()if __name__ == '__main__':    parser = argparse.ArgumentParser(description = 'Stackless Socket Server Example')    parser.add_argument('--localhost', action = 'store', dest = 'localhost',        default = LOCAL_SERVER_HOST)    parser.add_argument('--localport', action = 'store', dest = 'localport',        type = int, required = True)    parser.add_argument('--remotehost', action = 'store', dest = 'remotehost',        default = REMOTE_SERVER_HOST)    parser.add_argument('--remoteport', action = 'store', dest = 'remoteport',        type = int, default = 80)    given_args = parser.parse_args()    localhost, localport = given_args.localhost, given_args.localport    remotehost, remoteport = given_args.remotehost, given_args.remoteport    print('Starting port forwarding local {}:{} ==> {}:{}'.format(        localhost, localport, remotehost, remoteport))    PortForwarder(localhost, localport, remotehost, remoteport)    asyncore.loop()

运行脚本会看到:

$ python3 port_forwarding.py --localport 8800 --remotehost www.vlight.meStarting port forwarding local localhost:8800 ==> www.vlight.me:80Connected to: ('127.0.0.1', 52296)Connected to: ('127.0.0.1', 52300)Connected to: ('127.0.0.1', 52302)Connected to: ('127.0.0.1', 52304)Connected to: ('127.0.0.1', 52308)Connected to: ('127.0.0.1', 52310)

asyncore 在 3.6 后被弃用,使用 asyncio 替代。

通过 ICMP 查验网络中的主机

互联网控制消息协议(Internet Control Message Protocol,ICMP)

See:

  • 互联网控制消息协议
  • INTERNET CONTROL MESSAGE PROTOCOL RFC 792
  • Computing the Internet Checksum RFC 1071
#!/usr/bin/env python3# -*- coding:utf-8 -*-import osimport argparseimport socketimport structimport selectimport timeICMP_ECHO_REQUEST = 8DEFAULT_TIMEOUT = 2DEFAULT_COUNT = 4class Pinger(object):    def __init__(self, target_host, count = DEFAULT_COUNT,        timeout = DEFAULT_TIMEOUT):        self.target_host = target_host        self.count = count        self.timeout = timeout    def do_checksum(self, source_string):        sum = 0        max_count = (len(source_string) // 2) * 2        count = 0        # source_string = str(source_string)        while count < max_count:            val = source_string[count + 1] * 256 + source_string[count]            sum = sum + val            sum = sum & 0xffffffff            count = count + 2        if max_count < len(source_string):            sum = sum + source_string[len(source_string)-1]            sum = sum & 0xffffffff        sum = (sum >> 16) + (sum & 0xffff)        sum = sum + (sum >> 16)        answer = ~sum        answer = answer & 0xffff        answer = answer >> 8 | (answer << 8 & 0xff00)        return answer    def receive_pong(self, sock, ID, timeout):        time_remaining = timeout        while True:            Start_time = time.time()            readable = select.select([sock], [], [], time_remaining)            time_spent = (time.time() - Start_time)            if readable[0] == []:                return            time_received = time.time()            recv_packet, addr = sock.recvfrom(1024)            icmp_header = recv_packet[20: 28]            type, code, checksum, pack_ID, sequence = struct.unpack(                'bbHHh', icmp_header)            if pack_ID == ID:                bytes_In_double = struct.calcsize('d')                time_sent = struct.unpack('d',                    recv_packet[28:28+bytes_In_double])[0]                return time_received - time_sent            time_remaining = time_remaining - time_spent            if time_remaining <= 0:                return    def send_ping(self, sock, ID):        target_addr = socket.gethostbyname(self.target_host)        my_checksum = 0        # create a dummy header with 0 checksum        # header is type (8), code (8), checksum (16), id (16), sequence (16)        header = struct.pack(            'bbHHh', ICMP_ECHO_REQUEST, 0, my_checksum, ID, 1            )        bytes_In_double = struct.calcsize('d')        data = (192 - bytes_In_double) * 'Q'        data = struct.pack('d', time.time()) + data.encode()        # get the checksum on the data and the dummy header        my_checksum = self.do_checksum(header + data)        header = struct.pack(            'bbHHh', ICMP_ECHO_REQUEST, 0, socket.htons(my_checksum), ID, 1            )        packet = header + data        sock.sendto(packet, (target_addr, 1))    def ping_once(self):        icmp = socket.getprotobyname('icmp')        try:            sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)        except socket.error as e:            if e.errno == 1:                msg = 'ICMP message can only be sent from root user processes'                raise socket.error(msg)        except Exception as e:            print('Exception:', e)        my_ID = os.getpid() & 0xffff        self.send_ping(sock, my_ID)        delay = self.receive_pong(sock, my_ID, self.timeout)        sock.close()        return delay    def ping(self):        for i in range(self.count):            # print('Ping to {}...'.format(self.target_host))            try:                delay = self.ping_once()            except socket.gaierror as e:                print('Ping to {}... Ping failed. (socket error: {})'                    ''.format(self.target_host, e[1]))                break            if delay == None:                print('Ping to {}... Ping failed. (timeout within {}sec.)'                    ''.format(self.target_host, self.timeout))            else:                delay = delay * 1000                print('Ping to {}... Get pong in {:.4f}ms'                    ''.format(self.target_host, delay))if __name__ == '__main__':    parser = argparse.ArgumentParser(description = 'Python ping')    parser.add_argument('--targethost', action = 'store', dest = 'targethost',        required = True)    given_args = parser.parse_args()    targethost = given_args.targethost    pinger = Pinger(target_host = targethost)    pinger.ping()

运行脚本会看到:

$ sudo python3 ping_remote_host.py --targethost www.vlight.mePing to www.vlight.me... Get pong in 307.6901msPing to www.vlight.me... Get pong in 290.1580msPing to www.vlight.me... Get pong in 289.8428msPing to www.vlight.me... Get pong in 292.2680ms

等待远程网络服务上线

#!/usr/bin/env python# -*- coding: utf-8 -*-import argparseimport socketimport errnofrom time import time as nowDEFAULT_TIMEOUT = 120DEFAULT_SERVER_HOST = 'localhost'DEFAULT_SERVER_PORT = 80class NetServiceChecker(object):    def __init__(self, host, port, timeout = DEFAULT_TIMEOUT):        self.host = host        self.port = port        self.timeout = timeout        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    def end_wait(self):        self.sock.close()    def check(self):        if self.timeout:            end_time = now() + self.timeout        while True:            try:                if self.timeout:                    next_timeout = end_time - now()                    if next_timeout < 0:                        return False                    else:                        print('Setting socket next timeout {:0.0f}s'                        ''.format(next_timeout))                self.sock.connect((self.host, self.port))            except socket.error as e:                if self.timeout:                    return False            except socket.error as e:                print('Exception:', e)            else:                self.end_wait()                return Trueif __name__ == '__main__':    parser = argparse.ArgumentParser(description = 'Wait for Network Service')    parser.add_argument('--host', action = 'store', dest = 'host',    default = DEFAULT_SERVER_HOST)    parser.add_argument('--port', action = 'store', dest = 'port',    type = int, default = DEFAULT_SERVER_PORT)    parser.add_argument('--timeout', action = 'store', dest = 'timeout',    type = int, default = DEFAULT_TIMEOUT)    given_args = parser.parse_args()    host, port, timeout = given_args.host, given_args.port, given_args.timeout    service_checker = NetServiceChecker(host, port, timeout = timeout)    print('Checking for network service {}:{} ...'.format(host, port))    if service_checker.check():        print('Service is available again!')

运行脚本后会看到:

$ python3 wait_for_remote_service.pyChecking for network service localhost:80 ...Setting socket next timeout 120sService is available again!

枚举设备中的接口

#!/usr/bin/env python3import sysimport socketimport fcntlimport structimport arraySIOCGIFCONF = 0x8912 # from C library sockios.hSTRUCT_SIZE_32 = 32STRUCT_SIZE_64 = 40PLATEFORM_32_MAX_NUMBER = 2**32DEFAULT_INTERFACES = 8def list_interfaces():    interfaces = []    max_interfaces = DEFAULT_INTERFACES    is_64bits = sys.maxsize > PLATEFORM_32_MAX_NUMBER    struct_size = STRUCT_SIZE_64 if is_64bits else STRUCT_SIZE_32    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)    while True:        bytes = max_interfaces * struct_size        interface_names = array.array('B', bytes * '\0'.encode())        sock_info = fcntl.ioctl(        sock.fileno(),        SIOCGIFCONF,        struct.pack('iL', bytes, interface_names.buffer_info()[0])        )        outbytes = struct.unpack('iL', sock_info)[0]        if outbytes == bytes:            max_interfaces *= 2        else:            break    namestr = interface_names.tostring()    for i in range(0, outbytes, struct_size):        interfaces.append((namestr[i: i+16].decode().split('\0', 1)[0]))    return interfacesif __name__ == '__main__':    interfaces = list_interfaces()    print('This machine has {}'    ' network interfaces: {}.'.format(len(interfaces), interfaces))

运行脚本后会看到:

$ python3 list_network_interfaces.pyThis machine has 2 network interfaces: ['lo', 'wlp3s0'].

找出设备中某个接口的 IP 地址

#!/usr/bin/env python3import argparseimport sysimport socketimport fcntlimport structimport arraydef get_ip_address(ifname):    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)    return socket.inet_ntoa(fcntl.ioctl(        s.fileno(),        0x8915,        struct.pack('256s', ifname[:15].encode())        )[20:24])if __name__ == '__main__':    parser = argparse.ArgumentParser(description = 'Python networking utils')    parser.add_argument('--ifname', action  = 'store',        dest = 'ifname', required = True)    given_args = parser.parse_args()    ifname = given_args.ifname    print('Interface [{}] --> IP: {}'.format(ifname, get_ip_address(ifname)))

运行脚本后会看到:

python3 get_interface_ip_address.py --ifname wlp3s0Interface [wlp3s0] --> IP: 192.168.3.29

探测设备中的接口是否开启

需要安装 python-nmap 模块:

pip install python-nmap
#!/usr/bin/env python3import argparseimport socketimport structimport fcntlimport nmapSAMPLE_PORTS = '21-23'def get_interface_status(ifname):    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)    ip_address = socket.inet_ntoa(fcntl.ioctl(        sock.fileno(),        0x8915,        struct.pack('256s', ifname[:15].encode())        )[20:24])    nm = nmap.PortScanner()    nm.scan(ip_address, SAMPLE_PORTS)    return nm[ip_address].state()if __name__ == '__main__':    parser = argparse.ArgumentParser(description = 'Python networking utils')    parser.add_argument('--ifname', action = 'store',        dest = 'ifname', required = True)    given_args = parser.parse_args()    ifname = given_args.ifname    print('Interface [{}] is: {}'.format(ifname, get_interface_status(ifname)))

运行脚本后会发现:

python3 find_network_interface_status.py --ifname wlp3s0Interface [wlp3s0] is: up

检测网络中未开启的设备

需要安装 scapy 库:

pip install scapy
#!/usr/bin/env pythonimport argparseimport timeimport schedfrom scapy.all import(sr, srp, IP, UDP,    ICMP, TCP, ARP, Ether)RUN_FREQUENCY = 10scheduler = sched.scheduler(time.time, time.sleep)def detect_inactive_hosts(scan_hosts):    '''    scans the network to find scan_hosts are live or dead    scan_hosts can be like 10.0.2.2-4 to cover range.    See scapy docs for specifying targets    '''    global scheduler    scheduler.enter(RUN_FREQUENCY, 1, detect_inactive_hosts, (scan_hosts, ))    inactive_hosts = []    try:        ans, unans = sr(IP(dst = scan_hosts)/ICMP(), retry = 0, timeout = 1)        ans.summary(lambda (s, r): r.sprintf('%IP.src% is alive'))        for inactive in unans:            print(inactive.dst, 'is inactive')            inactive_hosts.append(inactive.dst)        print('Total {} host are inactive'.format(len(inactive_hosts)))    except KeyboardInterrupt:        exit(0)if __name__ == '__main__':    parser = argparse.ArgumentParser(description = 'Python networking utils')    parser.add_argument('--scan-hosts', action = 'store', dest = 'scan_hosts',        required = True)    given_args = parser.parse_args()    scan_hosts = given_args.scan_hosts    scheduler.enter(1, 1, detect_inactive_hosts, (scan_hosts, ))    scheduler.run()

运行脚本会发现:

$ sudo python detect_inactive_machines.py --scan-host 192.168.3.1-8Begin emission:.*..........Finished to send 8 packets.Received 12 packets, got 1 answers, remaining 7 packets192.168.3.1 is alive('192.168.3.3', 'is inactive')('192.168.3.4', 'is inactive')('192.168.3.5', 'is inactive')('192.168.3.2', 'is inactive')('192.168.3.7', 'is inactive')('192.168.3.8', 'is inactive')('192.168.3.6', 'is inactive')Total 7 host are inactive

使用 socketpair 执行基本的进程间通信

#!/usr/bin/env python3import socketimport osBUFSIZE = 1024def test_socketpair():    parent, child = socket.socketpair()    pid = os.fork()    try:        if pid:            print('@Parent, sending message...')            child.close()            parent.sendall(b'Hello from parent!')            response = parent.recv(BUFSIZE)            print('Response from child:', response)            parent.close()        else:            print('@Child waiting for message from parent')            parent.close()            message = child.recv(BUFSIZE)            print('Message from parent:', message)            child.sendall(b'Hello from child!!')            child.close()    except Exception as err:        print('Error:', err)if __name__ == '__main__':    test_socketpair()

OUTPUT:

$ python3 ipc_using_socketpairs.py@Parent, sending message...@Child waiting for message from parentMessage from parent: b'Hello from parent!'Response from child: b'Hello from child!!'

使用 Unix 域套接字执行进程间通信

SERVER:

#!/usr/bin/env python3import socketimport osimport timeSERVER_PATH = '/tmp/python_unix_socket_server'def run_unix_domain_socket_server():    if os.path.exists(SERVER_PATH):        os.remove(SERVER_PATH)    print('Starting unix domain socket server.')    server = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)    server.bind(SERVER_PATH)    print('Listening on path:', SERVER_PATH)    while True:        datagram = server.recv(1024)        if not datagram:            break        else:            print('-'*20)            print(datagram)            if 'DONE' == datagram:                break    print('-'*20)    print('Server is shutting down now...')    server.close()    os.remove(SERVER_PATH)    print('Server shutdown and path removed.')if __name__ == '__main__':    run_unix_domain_socket_server()

CLIENT:

#!/usr/bin/env python3import socketimport sysSERVER_PATH = '/tmp/python_unix_socket_server'def run_unix_domain_socket_client():    sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)    # connect the socket to the path where the server is listening    server_address = SERVER_PATH    print('connecting to', SERVER_PATH)    try:        sock.connect(server_address)    except socket.error as msg:        print('msg', file = sys.stderr)        sys.exit(1)    try:        message = 'This is the message. This will be echoed back!'        print('Sending:', message)        sock.sendall(message.encode())        amount_received = 0        amount_expected = len(message)        while amount_received < amount_expected:            data = sock.recv(16)            amount_received += len(data)            print('Received', data, file = sys.stderr)    finally:        print('Closing client')        sock.close()if __name__ == '__main__':    run_unix_domain_socket_client()

OUTPUT:

SERVER:

$ python3 unix_domain_socket_server.pyStarting unix domain socket server.Listening on path: /tmp/python_unix_socket_server--------------------b'This is the message. This will be echoed back!'

CLIENT:

$ python3 unix_domain_socket_client.pyconnecting to /tmp/python_unix_socket_serverSending: This is the message. This will be echoed back!

确认你使用的 Python 是否支持 IPv6 套接字

IP第6版(IPv6)在业内越来越多地被用来开发新型应用。如果你想编写一个IPv6应用程序,首先要知道你的设备是否支持 IPv6。在 Linux/Unix 中,可通过下面的命令确认:

$ cat /proc/net/if_inet600000000000000000000000000000001 01 80 10 80       lofe80000000000000677d365fd6526aaa 03 40 20 80   wlp3s0

使用Python脚本也可以检查你的设备是否支持IPv6,以及所安装的Python是否支持。

需要安装 netifaces :

$ pip install netifaces
#!/usr/bin/env python3import socketimport argparseimport netifaces as nidef inspect_ipv6_aupport():    print('IPv6 support built into Python:', socket.has_ipv6)    ipv6_addr = {}    for interface in ni.interfaces():        all_adresses = ni.ifaddresses(interface)        print('Interface {}:'.format(interface))        for family, addrs in all_adresses.items():            fam_name = ni.address_families[family]            print('  Address family:', fam_name)            for addr in addrs:                if fam_name == 'AF_INET6':                    ipv6_addr[interface] = addr['addr']                print('    Address  :', addr['addr'])                nmask = addr.get('netmask', None)                if nmask:                    print('    Netmask  :', nmask)                bcast = addr.get('broadcast', None)                if bcast:                    print('    Broadcast:', bcast)    if ipv6_addr:        print('Found IPv6 address:', ipv6_addr)    else:        print('No Ipv6 interface found!')if __name__ == '__main__':    inspect_ipv6_aupport()

OUTPUT:

$ python3 check_ipv6_support.pyIPv6 support built into Python: TrueInterface lo:  Address family: AF_PACKET    Address  : 00:00:00:00:00:00  Address family: AF_INET    Address  : 127.0.0.1    Netmask  : 255.0.0.0  Address family: AF_INET6    Address  : ::1    Netmask  : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128Interface enp4s0f2:  Address family: AF_PACKET    Address  : 08:60:6e:0f:54:3a    Broadcast: ff:ff:ff:ff:ff:ffInterface wlp3s0:  Address family: AF_PACKET    Address  : dc:85:de:8d:ee:c0    Broadcast: ff:ff:ff:ff:ff:ff  Address family: AF_INET    Address  : 192.168.3.29    Netmask  : 255.255.255.0    Broadcast: 192.168.3.255  Address family: AF_INET6    Address  : fe80::677d:365f:d652:6aaa%wlp3s0    Netmask  : ffff:ffff:ffff:ffff::/64Found IPv6 address: {'lo': '::1', 'wlp3s0': 'fe80::677d:365f:d652:6aaa%wlp3s0'}

从 IPv6 地址中提取 IPv6 前缀

在IPv6应用中,你要从 IPv6 地址中找出前缀信息。注意,按照 RFC 3513 的定义,前面的64位 IPv6 地址由全网路由前缀和子网ID组成。通常使用一个较短的前缀(例如 /48 ),可以定义很多更长、更具体的前缀(例如 /64 )。

#!/usr/bin/env pythonimport socketimport netifaces as niimport netaddr as nadef extract_ipv6_info():    print('IPv6 support built into Python:', socket.has_ipv6)    for interface in ni.interfaces():        all_addresses = ni.ifaddresses(interface)        print('Interface {}:'.format(interface))        for family, addrs in all_addresses.items():            fam_name = ni.address_families[family]            print('  Adress family:', fam_name)            for addr in addrs:                if fam_name == 'AF_INET6':                    addr = addr['addr']                    has_eth_string = addr.split('%')                    if has_eth_string:                        addr = addr.split('%')[0]                    print('    IP Address      :', na.IPNetwork(addr))                    print('    IP Version      :',na.IPNetwork(addr).version)                    print('    IP Prefix length:',                        na.IPNetwork(addr).prefixlen)                    print('    Network         :', na.IPNetwork(addr).network)                    print('    Broadcast       :',                        na.IPNetwork(addr).broadcast)if __name__ == '__main__':    extract_ipv6_info()

OUTPUT:

$ python3 extract_ipv6_prefix.pyIPv6 support built into Python: TrueInterface lo:  Adress family: AF_PACKET  Adress family: AF_INET  Adress family: AF_INET6    IP Address      : ::1/128    IP Version      : 6    IP Prefix length: 128    Network         : ::1    Broadcast       : ::1Interface enp4s0f2:  Adress family: AF_PACKETInterface wlp3s0:  Adress family: AF_PACKET  Adress family: AF_INET  Adress family: AF_INET6    IP Address      : fe80::677d:365f:d652:6aaa/128    IP Version      : 6    IP Prefix length: 128    Network         : fe80::677d:365f:d652:6aaa    Broadcast       : fe80::677d:365f:d652:6aaa

编写一个 IPv6 回显客户端/服务器

SERVER:

#!/usr/bin/env python3import argparseimport socketimport sysHOST = 'localhost'def echo_server(port, host = HOST):    for result in socket.getaddrinfo(host, port, socket.AF_UNSPEC,        socket.SOCK_STREAM, 0, socket.AI_PASSIVE):        af, socktype, proto, canonname, sa = result        try:            sock = socket.socket(af, socktype, proto)        except socket.error as e:            print(e)        try:            sock.bind(sa)            sock.listen(1)            print('Server listening on {}:{}'.format(host, port))        except socket.error as e:            sock.close()            continue        break        sys.exit(1)    conn, addr = sock.accept()    print('Connected to', addr)    while True:        data = conn.recv(1024)        print('Received data from the client: [{}]'.format(data))        if not data:            break        conn.send(data)        print('Sent data echoed back to the client: [{}]'.format(data))    conn.close()if __name__ == '__main__':    parser = argparse.ArgumentParser(description = 'IPv6 Socket Server')    parser.add_argument('--port', '-p',action = 'store', dest = 'port',        type = int, required = True)    given_args = parser.parse_args()    port = given_args.port    echo_server(port)

CLIENT:

#!/usr/bin/env python3import argparseimport socketimport sysHOST = 'localhost'def echo_server(port, host = HOST):    for result in socket.getaddrinfo(host, port, socket.AF_UNSPEC,        socket.SOCK_STREAM, 0, socket.AI_PASSIVE):        af, socktype, proto, canonname, sa = result        try:            sock = socket.socket(af, socktype, proto)        except socket.error as e:            print(e)        try:            sock.bind(sa)            sock.listen(1)            print('Server listening on {}:{}'.format(host, port))        except socket.error as e:            sock.close()            continue        break        sys.exit(1)    conn, addr = sock.accept()    print('Connected to', addr)    while True:        data = conn.recv(1024)        print('Received data from the client: [{}]'.format(data))        if not data:            break        conn.send(data)        print('Sent data echoed back to the client: [{}]'.format(data))    conn.close()if __name__ == '__main__':    parser = argparse.ArgumentParser(description = 'IPv6 Socket Server')    parser.add_argument('--port', '-p',action = 'store', dest = 'port',        type = int, required = True)    given_args = parser.parse_args()    port = given_args.port    echo_server(port)

OUTPUT:

SERVER:

$ python3 ipv6_echo_server.py -p 8800Server listening on localhost:8800Connected to ('127.0.0.1', 51668)Received data from the client: [b'Hello from ipv6 client']Sent data echoed back to the client: [b'Hello from ipv6 client']

CLIENT:

$ python3 ipv6_echo_client.py -p 8800Send data to server: b'Hello from ipv6 client'Received from server b'Hello from ipv6 client'
原创粉丝点击