socket 编程
理解网络编程基础:TCP、UDP、IP、端口
掌握 TCP Socket 的服务端和客户端编写流程
实现简单的双向通信程序
核心讲解
Socket(套接字)是网络编程的基础,是不同计算机之间进程通信的端点。Python 内置 socket 模块提供了套接字编程能力。
(1)核心概念
TCP:面向连接的可靠传输协议,三次握手,数据可靠有序,适合大多数场景
UDP:无连接的不可靠协议,速度快,可能丢包,适合视频、直播等场景
IP 地址:标识网络中的计算机
端口号:标识计算机中的进程,0-65535
(2)TCP Socket 编程流程
服务端:
创建套接字对象
绑定 IP 和端口:
bind()开始监听:
listen()等待客户端连接:
accept(),阻塞等待接收 / 发送数据:
recv()/send()关闭连接
客户端:
创建套接字对象
连接服务端:
connect()发送 / 接收数据
关闭连接
(3)注意点
recv(1024)一次最多接收 1024 字节,返回字节类型发送的数据必须是字节,字符串要
encode()编码TCP 是字节流,存在粘包问题,需要自定义协议处理
代码示例
# ===== TCP服务端 =====
import socket
import threading
def handle_client(conn, addr):
"""处理客户端连接"""
print(f"客户端 {addr} 已连接")
while True:
try:
# 接收数据
data = conn.recv(1024)
if not data:
break
msg = data.decode("utf-8")
print(f"收到 {addr}:{msg}")
# 回复数据
reply = f"收到:{msg}"
conn.send(reply.encode("utf-8"))
except:
break
conn.close()
print(f"客户端 {addr} 断开连接")
def tcp_server():
# 创建TCP套接字
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定地址和端口
server.bind(("127.0.0.1", 8888))
# 开始监听,最大等待连接数5
server.listen(5)
print("服务端启动,监听8888端口...")
while True:
# 等待客户端连接
conn, addr = server.accept()
# 每个客户端开一个线程处理
threading.Thread(target=handle_client, args=(conn, addr)).start()
# ===== TCP客户端 =====
def tcp_client():
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接服务端
client.connect(("127.0.0.1", 8888))
print("已连接到服务端")
while True:
msg = input("请输入消息:")
if msg == "exit":
break
# 发送数据
client.send(msg.encode("utf-8"))
# 接收回复
reply = client.recv(1024).decode("utf-8")
print("服务端回复:", reply)
client.close()
# 运行说明:先运行服务端,再运行客户端
# 实际使用时分别放在两个py文件中
if __name__ == "__main__":
# 启动服务端(实际项目分开运行)
# tcp_server()
# 启动客户端
# tcp_client()
pass
常见误区
字节和字符串混淆:socket 收发的都是字节,字符串必须 encode 编码,接收后 decode 解码
粘包问题:TCP 是流协议,连续发送小数据可能粘在一起,需要用长度前缀、分隔符等方式解决
端口占用:服务端端口被占用会报错,更换端口或者关闭占用程序
阻塞模式:默认 recv、accept 都是阻塞的,会卡住程序,多线程 / 异步才能处理多个连接
客户端连接失败:服务端没启动、防火墙拦截、IP 端口错误,都会连接失败
课后练习
编写 TCP 服务端和客户端,实现客户端发消息,服务端转大写后返回
实现一个简单的文件传输功能,客户端发送文件,服务端保存
尝试编写 UDP 版本的收发程序
思考:为什么 TCP 会有粘包问题,UDP 没有?

