
一、前言我们平时调用接口使用requests、aiohttp底层全部都是TCP协议。HTTP只是构建在TCP之上的应用层协议。很多运维、后端场景需要直接操作TCP裸连接端口连通性探测、自定义报文通信、服务心跳、Socket长连接。TCP是面向连接的可靠传输协议通信分为三步建立连接 → 收发数据 → 断开连接。本文使用Python内置socket库不依赖任何第三方库从零实现TCP客户端与服务端通信。二、TCP与UDP核心区别TCP需要先三次握手建立连接UDP直接发包TCP保证数据有序、不丢失UDP只管发送不保障送达TCP使用SOCK_STREAMUDP使用SOCK_DGRAMTCP适合文件传输、接口调用UDP适合广播、实时数据流。三、基础TCP客户端短连接请求短连接连接建立收发一次数据立刻关闭。核心方法socket() 创建套接字connect() 连接服务端IP端口send() 发送字节数据recv() 接收返回数据importsocket# 创建TCP套接字 SOCK_STREAM TCPclientsocket.socket(socket.AF_INET,socket.SOCK_STREAM)# 目标服务端地址host127.0.0.1port9000try:# 发起三次握手建立TCP连接client.connect((host,port))# 发送二进制数据client.send(Hello TCP Server.encode(utf-8))# 阻塞等待接收服务端返回数据缓冲区1024字节recv_dataclient.recv(1024)print(收到服务端返回,recv_data.decode(utf-8))exceptConnectionRefusedError:print(端口未开放TCP连接失败)finally:# 关闭连接释放资源client.close()四、TCP服务端监听端口并处理连接服务端固定端口监听等待客户端接入。关键函数bind() 绑定IP和端口listen() 开启监听accept() 阻塞等待新客户端接入importsocket serversocket.socket(socket.AF_INET,socket.SOCK_STREAM)# 绑定0.0.0.0允许局域网所有设备访问server.bind((0.0.0.0,9000))# 开启监听最大挂起队列5server.listen(5)print(TCP服务端已启动监听9000端口)whileTrue:# 阻塞等待客户端连接conn,addrserver.accept()print(f新客户端接入{addr})# 接收客户端消息dataconn.recv(1024)print(收到消息,data.decode())# 回复数据conn.send(消息已收到.encode(utf-8))# 关闭本次客户端连接短连接模式conn.close()运行顺序先启动服务端再运行客户端即可完成一次TCP通信。五、TCP长连接不断开持续收发数据短连接每次通信都要重新握手开销很大。长连接建立一次连接反复收发多条消息。客户端长连接代码importsocket clientsocket.socket(socket.AF_INET,socket.SOCK_STREAM)client.connect((127.0.0.1,9000))# 循环发送多条数据连接不断开foriinrange(3):msgf第{i1}条消息.encode(utf-8)client.send(msg)resclient.recv(1024)print(接收:,res.decode())client.close()服务端改造持续读取数据importsocket serversocket.socket(socket.AF_INET,socket.SOCK_STREAM)server.bind((0.0.0.0,9000))server.listen(5)whileTrue:conn,addrserver.accept()print(客户端已连接)# 持续读取客户端消息whileTrue:dataconn.recv(1024)ifnotdata:# 客户端关闭连接recv会拿到空字节breakprint(data.decode())conn.send(ok.encode())conn.close()六、实战场景1TCP端口存活检测运维最常用场景批量探测服务器端口是否开放本质就是尝试建立TCP连接。importsocketdefcheck_tcp_port(host,port,timeout2):socksocket.socket(socket.AF_INET,socket.SOCK_STREAM)sock.settimeout(timeout)try:sock.connect((host,port))returnTrue,端口开放exceptException:returnFalse,端口关闭或无法连接finally:sock.close()# 测试print(check_tcp_port(www.baidu.com,80))print(check_tcp_port(127.0.0.1,9999))这个端口探测比UDP探测更加可靠广泛用于内网资产扫描、节点健康检测。七、实战场景2手动发送原始HTTP报文裸TCP访问网页HTTP协议就是文本TCP报文我们不用requests直接用TCP套接字访问网页importsocket clientsocket.socket(socket.AF_INET,socket.SOCK_STREAM)client.connect((www.baidu.com,80))# 原始HTTP GET报文http_msgbGET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\nclient.send(http_msg)# 接收网页响应responseclient.recv(4096)print(response.decode(utf-8,errorsignore))client.close()运行就能拿到百度的HTTP响应头与网页正文可以直观理解HTTP是封装在TCP之上的应用层协议。八、TCP开发常见问题与避坑recv阻塞卡死recv默认无限等待可以设置sock.settimeout(3)超时断开。粘包问题TCP是流式字节流没有数据包边界多条数据会黏在一起。自定义通信协议时必须加数据长度分隔符。客户端没有正常close导致端口被占用TIME_WAIT程序一定要正常关闭套接字服务端可以开启端口复用server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)数据必须为bytes字节串字符串一定要encode不能直接发送str字符串。单线程服务端只能处理一个客户端上面的服务端是单线程一次只能服务一个连接高并发场景需要搭配多线程/多协程处理每一条TCP连接。九、异步TCPasyncio高级用法高并发大量TCP探测时同步socket效率太低可以使用asyncio创建异步TCP连接上万条连接轻松调度占用内存极低非常适合批量端口巡检。十、总结TCP核心流程创建套接字 → connect建立连接 → send/recv收发数据 → close断开短连接一发一关长连接复用TCP通道减少握手开销原生Socket TCP可以实现端口探测、自定义报文、裸HTTP请求requests、urllib、爬虫框架底层全部都是对TCP Socket的封装。原生TCP网络编程是后端、运维、网络爬虫的基本功掌握裸Socket通信才能真正理解互联网数据传输的底层逻辑。如果你想我可以再续写一版多线程TCP服务端 异步批量TCP端口检测代码。