当前位置:首页>python>用Python来了解网络连接的底层原理(一)

用Python来了解网络连接的底层原理(一)

  • 2026-09-02 20:14:27
用Python来了解网络连接的底层原理(一)
互联网时代依托于网络通信,今天我们就来用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'
IPV6是128位,分成8段,每段16位:
0123:4567:89ab:cdef:0123:4567:89ab:cdef
处理IPv6要用inet_pton:
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\hosts
127.0.0.1       localhost127.0.0.1       gitserver
为了性能,系统会缓存DNS结果,我们来用Python来解析DNS:
import socketprint(socket.getaddrinfo('baidu.com', 80))
当然,还有更好用的dnspython库可以尝试
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头部格式与解析。

最新文章

随机文章