Python TCP网络编程入门到实战:从原理到代码,手把手教你实现客户端与服务端通信

张开发
2026/5/21 13:40:58 15 分钟阅读
Python TCP网络编程入门到实战:从原理到代码,手把手教你实现客户端与服务端通信
在当下的互联网时代几乎所有应用都离不开网络通信——浏览网页、聊天软件、游戏联机、文件传输背后都藏着网络编程的核心逻辑。对于Python学习者而言掌握基础的网络编程不仅能理解“数据如何在网络中传输”更能亲手实现简单的客户端与服务端交互为后续学习更复杂的网络应用如爬虫、接口开发、分布式系统打下坚实基础。本文将从网络编程的核心概念入手逐步拆解TCP协议的工作机制再通过完整的代码示例手把手教你实现TCP客户端与服务端的通信最后总结常见问题及解决方案一、网络编程核心概念铺垫必懂否则代码看不懂在开始写代码之前我们必须先搞懂3个核心概念IP地址、端口号、Socket套接字以及TCP协议的作用。这几个概念就像“网络通信的基础工具”缺一不可。一 IP地址网络中设备的“身份证”IP地址是互联网中每一台设备的唯一标识相当于现实生活中的“家庭住址”——通过IP地址我们能准确找到网络中的某一台设备。常见的IP地址分为两类IPv4如192.168.40.128、127.0.0.1本机回环地址用于本机测试无论什么设备127.0.0.1都代表“自己”。IPv6由于IPv4地址资源有限后续逐渐普及的IPv6格式更长如2001:0db8:85a3:0000:0000:8a2e:0370:7334但目前Python网络编程中IPv4仍为最常用。简单说IP地址的作用是「定位设备」让数据知道要发送到哪台电脑。二端口号设备上程序的“门牌号”一台设备上可能同时运行多个网络程序如浏览器、微信、QQIP地址只能定位到设备却无法定位到设备上的某个程序——这时候就需要端口号。端口号是一个16位的整数范围0~65535相当于设备上每个网络程序的“门牌号”不同程序占用不同的端口号避免数据发送混乱。注意事项0~1023 是系统预留端口如80端口用于HTTP网页、22端口用于SSH远程连接我们自己写程序时建议使用 1024~65535 之间的端口。同一台设备上同一个端口号不能被两个程序同时占用否则会报“端口被占用”错误。简单说端口号的作用是「定位程序」让数据知道要发送到设备上的哪个程序。三Socket套接字程序间通信的“工具”有了IP地址定位设备和端口号定位程序我们已经能找到目标程序但数据如何在两个程序之间传输这就需要Socket。Socket套接字是Python内置的一个网络通信接口工具它封装了TCP/IP协议的底层细节让我们不用去理解复杂的协议原理就能轻松实现程序间的 data 收发。形象比喻Socket 就像网络版的“电话”——两个程序要通信各自都要创建一个Socket相当于各自拿一部电话一方拨号建立连接另一方接听监听连接然后就能互相“说话”收发数据结束后挂断关闭Socket。四TCP协议可靠的“数据传输协议”网络编程中最常用的协议有两种TCP 和 UDP。本文重点讲解 TCP 协议应用最广泛如网页、聊天、文件传输。TCP协议的核心特点重点面向连接通信前必须先建立连接类似打电话先拨号再说话通信结束后关闭连接。可靠传输数据不会丢失、不会乱序即使网络不稳定TCP也会自动重传丢失的数据确保接收方收到完整的数据。面向字节流数据以字节的形式传输接收方收到的数据顺序和发送方发送的顺序完全一致。对比UDP了解即可UDP 无连接、速度快但可能丢包适合对实时性要求高如视频直播、游戏联机的场景。二、Python TCP网络编程核心流程重中之重TCP网络编程分为「客户端」和「服务端」两部分两者的工作流程不同必须严格遵循以下步骤否则会出现连接失败、数据收发异常等问题。一服务端流程被动等待连接相当于“接电话的人”服务端的核心作用是监听端口、等待客户端连接、收发数据、关闭连接。流程分为7步固定模板记熟即可1.创建对象(socket服务器套接字对象):socket()参数1:ipv4类型地址 参数2: TCP协议 返回值: socket对象2.绑定服务器ip地址和端口号:bind()参数:服务器信息元组(服务器ip地址 , 服务器端口号)3.服务器对象设置监听:listen()参数: 最大等待连接数4.服务器等待接受客户端连接请求(直到接通为止):accept()返回值:元组类型(接通后的服务器对象,客户端信息元组)5.从接通后的服务器对象中接收客户端口发来的数据(二进制格式):recv()参数: 接收数据的长度 返回值:二进制类型6.接通后的服务器对象给客户端发送数据(二进制格式):send()参数: 给客户端的二进制数据7.关闭socket服务器套接字对象:close()注意: 接通后的服务器对象和接通前的服务器对象都需要关闭二客户端流程主动发起连接相当于“打电话的人”客户端的核心作用是主动连接服务端、收发数据、关闭连接。流程分为5步固定模板TCP 客户端程序开发流程及应用实践五步走① 创建客户端套接字对象socket()② 和服务器端套接字建立连接connect(和服务端套接字建立连接)③ 发送数据send(发送数据)④ 接收数据recv(接收数据)⑤ 关闭客户端套接字close(关闭连接)三、完整代码实现下面我们实现一个“简单的双向聊天”程序客户端发送消息服务端接收并回复双方可以互相收发一次消息全程可直接复制运行注意先运行服务端再运行客户端。一TCP服务端代码importsocket# 1. 导入socket模块内置无需安装# 2. 创建服务端套接字对象# socket.AF_INET使用IPv4协议# socket.SOCK_STREAM使用TCP协议流式套接字tcp_server_socketsocket.socket(socket.AF_INET,socket.SOCK_STREAM)# 3. 设置端口复用关键避免程序关闭后端口被占用报错10048# socket.SOL_SOCKET对当前套接字生效# socket.SO_REUSEADDR开启端口复用功能# True开启False关闭tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)# 4. 绑定IP地址和端口号# 第一个参数IP地址空字符串表示绑定本机所有IP如127.0.0.1、192.168.40.128等# 第二个参数端口号1024~65535之间这里用8888tcp_server_socket.bind((,8888))# 5. 开启监听进入等待连接状态# 参数128表示最大等待连接数最多允许128个客户端同时等待连接tcp_server_socket.listen(128)print(服务端已启动监听端口8888等待客户端连接...)# 6. 等待客户端连接阻塞状态直到有客户端连接过来# accept()方法返回两个值# ① conn_socket新的套接字对象专门用于和当前这个客户端通信相当于“专属客服”# ② ip_port客户端的IP地址和端口号元组格式如(127.0.0.1, 5678)conn_socket,ip_porttcp_server_socket.accept()print(f客户端{ip_port}已连接成功)# 7. 收发数据# 7.1 接收客户端发送的数据# recv(1024)表示一次最多接收1024字节的数据可根据需求调整# 网络传输的是字节数据所以需要用decode()解码成字符串recv_dataconn_socket.recv(1024)print(f收到客户端{ip_port}的消息{recv_data.decode(utf-8)})# 7.2 给客户端发送回复消息# 发送数据时需要用encode()将字符串编码成字节数据和客户端编码格式保持一致send_msg客户端你好你的消息我已经收到啦conn_socket.send(send_msg.encode(utf-8))print(服务端回复消息已发送)# 8. 关闭套接字先关和客户端通信的新套接字再关服务端监听套接字conn_socket.close()print(f与客户端{ip_port}的连接已关闭)tcp_server_socket.close()print(服务端已关闭)二TCP客户端代码importsocket# 1. 导入socket模块# 2. 创建客户端套接字对象和服务端协议一致IPv4 TCPtcp_client_socketsocket.socket(socket.AF_INET,socket.SOCK_STREAM)# 3. 连接服务端关键IP和端口必须和服务端一致# 参数是一个元组(服务端IP地址, 服务端端口号)# 本机测试用127.0.0.1局域网测试用服务端的局域网IP如192.168.40.128tcp_client_socket.connect((127.0.0.1,8888))print(客户端已成功连接服务端)# 4. 收发数据# 4.1 给服务端发送消息编码格式和服务端一致用utf-8send_msg服务端你好我是客户端tcp_client_socket.send(send_msg.encode(utf-8))print(客户端消息已发送)# 4.2 接收服务端的回复recv_datatcp_client_socket.recv(1024)print(f收到服务端的回复{recv_data.decode(utf-8)})# 5. 关闭客户端套接字通信结束tcp_client_socket.close()print(客户端已关闭)四、代码运行步骤第一次运行会报错核心原因是“运行顺序错误”或“IP/端口不一致”请严格按照以下步骤操作打开两个PyCharm窗口或两个终端分别粘贴服务端代码和客户端代码。先运行「服务端代码」运行后控制台会显示“服务端已启动监听端口8888等待客户端连接...”此时服务端处于阻塞状态等待客户端连接。再运行「客户端代码」运行后客户端会连接服务端双方互相收发消息最终关闭连接。运行成功效果服务端控制台服务端已启动监听端口8888等待客户端连接... 客户端 (127.0.0.1, 5678) 已连接成功 收到客户端 (127.0.0.1, 5678) 的消息服务端你好我是客户端 服务端回复消息已发送 与客户端 (127.0.0.1, 5678) 的连接已关闭 服务端已关闭客户端控制台客户端已成功连接服务端 客户端消息已发送 收到服务端的回复客户端你好你的消息我已经收到啦 客户端已关闭五、常见报错及解决方案运行过程中新手最容易遇到以下3个报错这里给出具体原因和解决方案不用再到处查资料报错1OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次原因端口被占用之前运行的服务端没关干净或其他程序占用了8888端口。解决方案优先选方法1最简单方法1换一个端口号如把8888改成9999同时修改服务端和客户端的端口保持一致。方法2关闭后台占用端口的进程Windows系统打开任务管理器 → 详细信息 → 找到python.exe结束进程Mac/Linux终端输入 lsof -i:8888找到进程ID用kill -9 进程ID 结束进程。方法3确保服务端代码中加了“端口复用”代码本文代码已加无需额外修改。报错2ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝无法连接原因按概率排序1. 先运行了客户端再运行服务端顺序反了。2. 客户端连接的IP或端口和服务端绑定的IP或端口不一致。3. 服务端没有正常启动如端口被占用导致服务端启动失败。解决方案严格按照“先运行服务端再运行客户端”的顺序操作。检查客户端的 connect() 方法IP和端口必须和服务端的 bind() 方法一致。本机测试时客户端IP用127.0.0.1避免局域网IP错误。报错3UnicodeDecodeError: #39;utf-8#39; codec can#39;t decode byte 0xb0 in position 0: invalid start byte原因客户端和服务端的编码/解码格式不一致如服务端用gbk解码客户端用utf-8编码。解决方案统一编码格式本文用的是utf-8确保客户端的 encode(#39;utf-8#39;) 和服务端的 decode(#39;utf-8#39;) 保持一致不要混用gbk和utf-8。六、代码优化上面的基础代码只能实现“一次收发消息”通信结束后程序就关闭了。实际应用中我们希望服务端能一直接受新客户端连接且能和同一个客户端持续聊天。下面给出优化后的代码带循环和异常捕获避免程序崩溃。优化后TCP服务端可循环接收客户端持续聊天importsocket tcp_server_socketsocket.socket(socket.AF_INET,socket.SOCK_STREAM)tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)tcp_server_socket.bind((,8888))tcp_server_socket.listen(128)print(服务端已启动监听端口8888等待客户端连接...)# 外层循环一直接受新的客户端连接whileTrue:try:# 等待客户端连接conn_socket,ip_porttcp_server_socket.accept()print(f客户端{ip_port}已连接成功)# 内层循环和当前客户端持续聊天whileTrue:try:# 接收客户端消息如果客户端断开会抛出ConnectionResetErrorrecv_dataconn_socket.recv(1024)# 如果客户端发送空消息说明客户端主动关闭连接ifnotrecv_data:print(f客户端{ip_port}主动断开连接)breakprint(f客户端{ip_port}{recv_data.decode(utf-8)})# 服务端发送消息手动输入send_msginput(服务端回复)conn_socket.send(send_msg.encode(utf-8))exceptConnectionResetError:# 客户端强制断开如关闭窗口捕获异常避免程序崩溃print(f客户端{ip_port}强制断开连接)break# 关闭和当前客户端的连接conn_socket.close()exceptExceptionase:# 捕获其他异常避免服务端崩溃print(f服务端出错{e})break# 关闭服务端监听套接字tcp_server_socket.close()print(服务端已关闭)优化后TCP客户端可持续和服务端聊天importsocket tcp_client_socketsocket.socket(socket.AF_INET,socket.SOCK_STREAM)# 连接服务端tcp_client_socket.connect((127.0.0.1,8888))print(客户端已成功连接服务端可开始聊天输入退出关闭连接)# 循环聊天whileTrue:# 客户端发送消息send_msginput(客户端发送)# 如果输入“退出”关闭客户端ifsend_msg退出:print(客户端主动关闭连接)break# 发送消息tcp_client_socket.send(send_msg.encode(utf-8))# 接收服务端回复recv_datatcp_client_socket.recv(1024)ifnotrecv_data:print(服务端已关闭连接)breakprint(f服务端回复{recv_data.decode(utf-8)})# 关闭客户端tcp_client_socket.close()通过本文的学习你已经掌握了Python TCP网络编程的核心3个基础概念IP定位设备、端口定位程序、Socket通信工具。2个核心流程服务端监听→等待连接→收发数据→关闭、客户端连接→收发数据→关闭。1个关键协议TCP可靠、面向连接适合大部分场景。常见报错解决端口占用、连接拒绝、编码不一致这3个报错解决了基本能应对80%的新手问题。

更多文章