问题现象与背景分析
当开发者使用websockets库的accept()方法建立WebSocket连接时,高频出现的ConnectionResetError: [Errno 104] Connection reset by peer异常常令开发者困扰。该错误通常发生在以下场景:
- 客户端突然断开TCP连接(非正常WebSocket关闭握手)
- 服务器端读取缓冲区时发现连接已重置
- 网络中间设备(如防火墙)主动终止连接
底层协议栈原理
该错误的本质是TCP协议层的RST(Reset)报文触发了操作系统内核的套接字错误。WebSocket作为应用层协议,建立在TCP三次握手基础上,当底层连接异常终止时:
+-----------+ +-----------+ | Client | RST | Server | | |------>| accept() | +-----------+ +-----------+
此时服务器调用accept()会立即触发异常,因为操作系统已检测到连接状态异常。
6种解决方案及代码实现
方案1:增加连接超时参数
async with websockets.connect(
"ws://example.com",
timeout=10.0, # 增加超时控制
ping_interval=None
) as websocket:
# 业务逻辑
方案2:实现自动重连机制
通过装饰器模式封装自动重试逻辑:
def autoreconnect(max_retries=3):
def decorator(func):
async def wrapper(*args, **kwargs):
for i in range(max_retries):
try:
return await func(*args, **kwargs)
except ConnectionResetError:
if i == max_retries - 1:
raise
await asyncio.sleep(2**i)
return wrapper
return decorator
方案3:调整操作系统TCP参数
修改Linux系统配置(需要sudo权限):
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
性能优化建议
| 参数 | 推荐值 | 作用 |
|---|---|---|
| SO_KEEPALIVE | True | 启用TCP保活探测 |
| ping_interval | 20s | WebSocket层心跳间隔 |
监控与诊断方法
- 使用
tcpdump抓取网络报文:
tcpdump -i eth0 'tcp port 8080' -w websocket.pcap - 分析Wireshark中的TCP序列号异常
- 检查Nginx等代理服务器的连接超时配置