Python Socket 零基础实战:从单次 TCP 通信到多线程并发聊天室
·
一、Socket 编程基础认知
1.1 通俗理解 Socket
Socket 可以类比电话机,网络通信必须由 ** 服务端(接听电话)和客户端(拨打电话)** 两端程序组成,二者通过 IP + 端口建立网络链路,完成数据收发。Python 内置socket标准库,原生支持 IPv4/IPv6、TCP/UDP 两种主流传输协议:
AF_INET:固定代表 IPv4 地址协议;SOCK_STREAM:TCP 协议(面向连接、可靠传输);SOCK_DGRAM:UDP 协议(无连接、不可靠报文传输)。
1.2 字节编码规则
计算机网络只支持二进制字节流传输,字符串与字节互转是中文收发必备操作:
encode("utf-8"):字符串→二进制 bytes,用于发送数据;decode("utf-8"):二进制 bytes→字符串,用于接收数据。
1.3 TCP 通信固定流程
- 服务端执行顺序:创建 socket → bind (绑定 IP + 端口) → listen (开启监听) → accept (阻塞等待连接) → recv/send (收发数据) → close (关闭套接字)
- 客户端执行顺序:创建 socket → connect (连接服务端地址) → send/recv (收发数据) → close (关闭套接字)
二、最简 TCP 单次通信实现(一问一答即断开)
该示例实现客户端发一条消息、服务端回复一条消息,随即两端断开连接,是 TCP 最基础通信模型。
2.1 服务端代码(server.py)
python
运行
import socket
# 1. 创建IPv4+TCP类型套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 获取本机主机名,自定义通信端口8000
host = socket.gethostname()
port = 8000
# 3. 绑定IP与端口
server_socket.bind((host, port))
# 4. 开启监听,最大挂起等待连接数5
server_socket.listen(5)
# 5. 阻塞等待客户端接入,返回连接对象+客户端地址
client_socket, client_addr = server_socket.accept()
print(f"接收到来自{client_addr}的连接")
# 6. 接收客户端数据,单次最大接收1024字节并解码
data = client_socket.recv(1024).decode('utf-8')
print(f"客户端说:{data}")
# 7. 服务端返回应答信息,编码为字节发送
client_socket.send("好的,收到".encode("utf-8"))
# 8. 依次关闭连接套接字、服务端监听套接字
client_socket.close()
server_socket.close()
2.2 客户端代码(client.py)
python
运行
import socket
# 1. 创建客户端套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 与服务端保持一致的IP、端口
host = socket.gethostname()
port = 8000
# 2. 主动连接服务端
client_socket.connect((host, port))
# 3. 发送消息,必须编码成字节
client_socket.send("你好,在吗?".encode('utf-8'))
# 4. 接收服务端返回数据并解码
data = client_socket.recv(1024).decode('utf-8')
print(f"服务器回:{data}")
# 关闭客户端连接
client_socket.close()
2.3 运行步骤与效果
- 优先运行
server.py,程序卡在accept()处阻塞,等待客户端连接; - 新开终端运行
client.py;
- 客户端控制台输出:
服务器回:好的,收到,程序结束; - 服务端控制台打印客户端地址与发送内容,随即关闭进程。
三、代码迭代 1:while 循环实现单客户端持续聊天
单次通信只能交互一句话,通过双层 while 循环改造代码,实现客户端和服务端自由持续对话,输入自定义指令才可断开。
3.1 改造后服务端
python
运行
# server.py
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
port = 8000
server.bind((host, port))
server.listen(5)
# 外层循环:持续等待新客户端连接
while True:
client, addr = server.accept()
# 内层循环:和当前接入的客户端持续聊天
while True:
data = client.recv(1024).decode("utf-8")
# 客户端断开连接时recv返回空字符串,跳出聊天循环
if not data:
print("客户端断开了连接")
break
print(f"{addr}说:{data}")
# 控制台手动输入回复内容
msg = input("服务端说:")
client.send(msg.encode("utf-8"))
client.close()
3.2 改造后客户端
python
运行
# client.py
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
port = 8000
client.connect((host, port))
while True:
msg = input("客户端说:")
# 输入exit退出客户端程序
if msg == 'exit':
break
client.send(msg.encode("utf-8"))
data = client.recv(1024).decode("utf-8")
print(f"服务器说:{data}")
client.close()
使用方式:两端循环输入文字聊天,客户端输入
exit即可断开连接。
四、单线程服务端核心短板分析
上述代码为单线程串行模型,存在致命缺陷:
- 客户端 A 成功接入后,服务端会陷入内层聊天循环,阻塞在
input/recv代码处; - 此时新客户端 B 发起连接请求,
accept()无法被执行,连接请求排队阻塞; - 只有 A 主动断开连接、内层循环结束,服务端回到外层
accept(),才能接收 B 的连接。
结论:单线程服务端同一时间仅能服务 1 个客户端,无法实现多用户同时在线。
五、代码迭代 2:多线程改造实现多客户端并发接入
引入 Python 内置threading多线程模块,将单个客户端通信逻辑封装为独立函数,每接入一个客户端就创建一个子线程处理通信,主线程持续等待新连接,实现多客户端并发在线。
多线程版服务端完整代码
python
运行
# server.py
import socket
import threading
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
port = 8000
server.bind((host, port))
server.listen(5)
# 单个客户端的通信处理函数
def handle_client(client,addr):
while True:
data = client.recv(1024).decode("utf-8")
if not data:
print(f"{addr}客户端断开了连接")
break
print(f"{addr}说:{data}")
msg = input("服务端说:")
client.send(msg.encode("utf-8"))
client.close()
# 主线程循环接收连接
while True:
client, addr = server.accept()
# 创建子线程绑定通信函数,传入客户端连接与地址参数
t = threading.Thread(target=handle_client, args=(client,addr))
t.start()
客户端代码沿用第三节长连接版本即可,可同时开启多个客户端终端连接服务端。
当前代码遗留问题
代码中服务端通过input()手动输入回复消息,多客户端并发聊天时,键盘输入无法区分消息要回复给哪个客户端,消息发送错乱。 优化思路:移除服务端input(),把服务端改成消息广播转发服务器:任一客户端发送的消息,由服务端统一转发给所有在线客户端,实现简易群聊聊天室。
六、项目优化方向与拓展学习路线
6.1 现有项目优化点
- 实现广播聊天室:维护在线客户端连接列表,收到消息后遍历列表全员推送;
- 增加端口复用配置,避免程序频繁启停出现端口占用报错;
- 增加异常捕获,处理网络断开、编码错误等异常。
6.2 Socket 进阶学习路线
- UDP 无连接套接字编程,对比 TCP/UDP 使用场景差异;
- IO 多路复用(select/poll/epoll),实现高并发服务端(优于多线程资源开销);
- 使用 Python 内置
socketserver封装库快速搭建 TCP 服务; - 基于 Socket 实现简易文件传输、即时通讯 IM 软件。
七、总结
- TCP 服务端核心流程:
bind-listen-accept,客户端:connect,收发数据必须做字符串 / 字节编解码; - 单线程 Socket 只能串行处理客户端,多线程是低成本实现并发的入门方案;
- Socket 是 HTTP、WebSocket 等上层网络协议的底层基础,熟练原生 Socket 有助于深入理解爬虫、后端接口、即时通讯底层原理。
更多推荐

所有评论(0)