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'
阅读全文
0 0
- IPv6、Unix 域套接字和网络接口
- 《Python网络编程》Part4 IPv6、Unix域套接字和网络接口
- UNIX 套接字网络编程接口
- 《网络编程》Unix 域套接字
- 网络编程练习-unix域套接字
- UNIX网络编程——UNIX域套接字编程和socketpair 函数
- 《Unix网络编程》卷1:套接字联网API(第3版):名字与地址互换、IPv4和IPv6互操作性
- UNIX网络编程:套接字
- linux网络编程之socket(十五):UNIX域套接字编程和socketpair 函数
- linux网络编程之socket(十五):UNIX域套接字编程和socketpair 函数
- linux网络编程之socket(十五):UNIX域套接字编程和socketpair 函数
- Unix域套接字
- UNIX域套接字
- UNIX域套接字
- Unix域套接字
- unix域套接字
- Unix域套接字
- UNIX域套接字
- 记录,关于鼠标的函数
- 在Ubuntu下搭建C/C++编程环境(vim+gcc+gdb)
- Table is marked as crashed and should be repaired
- phylip的具体使用方法
- 如何安全的存储密码
- IPv6、Unix 域套接字和网络接口
- 养成良好的C语言规范(一个好的开始是成功的一半)
- JS组件系列——表格组件神器:bootstrap table(二:父子表和行列调序)
- 中文搜索引擎集成--Xunsearch
- SQL 常用判断语句
- tcp接收策略
- 单片机 C51 编程要点总结
- 《自制搜索引擎》笔记(2)-迷你全文检索引擎Wiser-项目概述
- 家庭媒体中心解决方案(五、群晖系列nas基本功能使用指南篇3-网络记事本和远程监控)