互联网时代依托于网络通信,今天我们就来用python来看看网络连接的基础。让我们先从一个简单的TCP服务端开始。我们直接用Python内置的socketserver模块import socketserverclass MyTCPHandler(socketserver.StreamRequestHandler): """ 服务端请求处理类 每建立一个连接就会实例化一次 必须重写 handle() 方法来实现与客户端通信 """ def handle(self): # self.request 是与客户端连接的 TCP socket self.data = self.request.recv(1024).strip() print(f"{self.client_address} 发送了:") print(self.data) # 原样返回,但是转为大写 self.request.sendall(self.data.upper())if __name__ == "__main__": HOST, PORT = "localhost", 5555 # 创建服务器,绑定本地 5555 端口 with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server: # 持续运行,直到 Ctrl+C 中断 server.serve_forever()
通过socketserver.TCPServer(HOST,PORT),MyTCPHandler) 来进行端口绑定,程序向操作系统申请占用端口5555,直到程序退出才释放。同时注册一个请求处理器,客户端一连接就会执行handle()。StreamRequestHandler把客户端连接抽象成类文件对象:self.rfile.readline().strip()
在真实的环境中,如果客户端一直不发送换行符,连接会一直挂着。大量的这种请求会耗尽服务端连接,形成拒绝服务攻击。import socketMSG = bytearray("Hello World", 'utf-8')# 创建 TCP 套接字connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)connection.connect(("127.0.0.1", 5555))print(connection.getsockname())connection.send(MSG)# 接收大写后的数据result = connection.recv(len(MSG.upper()))print(result)
网络通信的本质是字节bytearray把字符串按指定编码UTF-8转为字节序列。socket.socket(socket.AF_INET, socket.SOCK_STREAM)
AF_INET:使用IPV4;SOCK_STREAM:代表TCP连接# 服务端输出('127.0.0.1', 57990) wrote:b'Hello World'
#客户都输出('127.0.0.1', 57990)b'HELLO WORLD'
接下来我们看一个重要的概念“端口”,它的规范来自IETF的RFC8335,端口与服务名的映射由IANA维护,Python socket模块自带端口与服务名映射工具:import socketprint(socket.getservbyname('http')) # 80print(socket.getservbyport(80)) # http
再下来是IP地址,网络通信实际上只认二进制,IP地址本质是32位整数(IPv4)。127.0.0.1我们用python代码来查看:import socketimport structip_binary = socket.inet_aton('127.0.0.1')print(struct.unpack('BBBB', ip_binary)) # (127, 0, 0, 1)print(ip_binary) # b'\x7f\x00\x00\x01'
0123:4567:89ab:cdef:0123:4567:89ab:cdef
socket.inet_pton(socket.AF_INET6, '0123:4567:89ab:cdef:0123:4567:89ab:cdef')
ipaddress模块,可以直接从二进制构建IP对象,并判断属性:import ipaddressip = ipaddress.IPv4Address('127.0.0.1')print(ip.is_loopback) # Trueprint(ip.is_global) # Falseprint(ip.is_private) # True
DNS系统负责把域名翻译成IP,本地优先级host文件:windows下的host文件在C:\Windows\System32\drivers\etc\hosts127.0.0.1 localhost127.0.0.1 gitserver
为了性能,系统会缓存DNS结果,我们来用Python来解析DNS:import socketprint(socket.getaddrinfo('baidu.com', 80))
from dns.resolver import resolvefrom dns.rdatatype import RdataTypefor qtype in RdataType: try: ans = resolve('www.baidu.com', qtype) for record in ans: print(f"{RdataType.to_text(qtype)}: {record}") except: continue
A: 183.2.172.17CNAME: www.a.shifen.com.AAAA: 240e:ff:e020:99b:0:ff:b099:cff1
• A:IPv4 地址• AAAA:IPv6 地址• CNAME:别名• NS:域名服务器• MX:邮件服务器• TXT:验证、SPF 等• SOA:权威信息
上面就是最基础的内容,或许下次我们可以看看IP头部格式与解析。