本文目录导读:

在 Python WebSocket 客户端中实现自动重连,有多种方法,这里提供几种常用且稳定的实现方案:
使用 websockets 库 + 循环重连(推荐)
import asyncio
import websockets
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class WebSocketClient:
def __init__(self, uri, max_retries=5, retry_delay=3):
self.uri = uri
self.max_retries = max_retries
self.retry_delay = retry_delay
self.websocket = None
self.running = False
async def connect(self):
"""建立 WebSocket 连接"""
try:
self.websocket = await websockets.connect(self.uri)
logger.info(f"Connected to {self.uri}")
return True
except Exception as e:
logger.error(f"Failed to connect: {e}")
return False
async def reconnect(self):
"""重连逻辑"""
retries = 0
while retries < self.max_retries:
logger.info(f"Reconnecting... attempt {retries + 1}/{self.max_retries}")
if await self.connect():
return True
retries += 1
if retries < self.max_retries:
await asyncio.sleep(self.retry_delay)
logger.error("Max reconnection attempts reached")
return False
async def send_message(self, message):
"""发送消息"""
if self.websocket:
try:
await self.websocket.send(message)
return True
except websockets.ConnectionClosed:
logger.warning("Connection closed while sending")
return False
return False
async def receive_messages(self):
"""接收消息的主循环"""
self.running = True
while self.running:
try:
if not self.websocket:
if not await self.reconnect():
break
message = await asyncio.wait_for(
self.websocket.recv(),
timeout=30
)
self.handle_message(message)
except asyncio.TimeoutError:
# 超时处理,保持连接活跃
try:
await self.websocket.ping()
except:
self.websocket = None
continue
except websockets.ConnectionClosed:
logger.warning("Connection lost, attempting to reconnect...")
self.websocket = None
if not await self.reconnect():
break
except Exception as e:
logger.error(f"Unexpected error: {e}")
self.websocket = None
await asyncio.sleep(self.retry_delay)
def handle_message(self, message):
"""处理接收到的消息"""
logger.info(f"Received: {message}")
async def close(self):
"""关闭连接"""
self.running = False
if self.websocket:
await self.websocket.close()
# 使用示例
async def main():
client = WebSocketClient("wss://echo.websocket.org")
try:
# 启动接收消息的任务
receive_task = asyncio.create_task(client.receive_messages())
# 等待一段时间后发送消息
await asyncio.sleep(2)
await client.send_message("Hello, WebSocket!")
# 模拟网络断开(仅用于测试)
await asyncio.sleep(5)
# 等待接收任务完成
await receive_task
except KeyboardInterrupt:
await client.close()
if __name__ == "__main__":
asyncio.run(main())
使用 websocket-client 库 + 回调重连
import websocket
import json
import time
import logging
from threading import Thread
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class WebSocketClient:
def __init__(self, url, reconnect_interval=5, max_reconnect_attempts=10):
self.url = url
self.reconnect_interval = reconnect_interval
self.max_reconnect_attempts = max_reconnect_attempts
self.ws = None
self.running = False
self.reconnect_attempts = 0
def on_message(self, ws, message):
"""消息回调"""
logger.info(f"Received: {message}")
def on_error(self, ws, error):
"""错误回调"""
logger.error(f"Error: {error}")
def on_close(self, ws, close_status_code, close_msg):
"""关闭回调"""
logger.info(f"Connection closed: {close_status_code} - {close_msg}")
if self.running:
self.reconnect()
def on_open(self, ws):
"""打开回调"""
logger.info("Connection established")
self.reconnect_attempts = 0
def connect(self):
"""建立连接"""
websocket.enableTrace(False)
self.ws = websocket.WebSocketApp(
self.url,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close,
on_open=self.on_open
)
# 启动运行线程
self.running = True
wst = Thread(target=self.ws.run_forever)
wst.daemon = True
wst.start()
def reconnect(self):
"""重连逻辑"""
while self.running and self.reconnect_attempts < self.max_reconnect_attempts:
self.reconnect_attempts += 1
logger.info(f"Reconnecting... attempt {self.reconnect_attempts}/{self.max_reconnect_attempts}")
try:
time.sleep(self.reconnect_interval)
self.connect()
break
except Exception as e:
logger.error(f"Reconnection failed: {e}")
if self.reconnect_attempts >= self.max_reconnect_attempts:
logger.error("Max reconnection attempts reached")
self.running = False
def send(self, message):
"""发送消息"""
if self.ws and self.ws.sock:
try:
if isinstance(message, dict):
message = json.dumps(message)
self.ws.send(message)
logger.info(f"Sent: {message}")
return True
except Exception as e:
logger.error(f"Failed to send message: {e}")
return False
def close(self):
"""关闭连接"""
self.running = False
if self.ws:
self.ws.close()
# 使用示例
def main():
client = WebSocketClient("wss://echo.websocket.org")
client.connect()
try:
# 发送消息
time.sleep(2)
client.send("Hello, WebSocket!")
# 保持运行
while True:
time.sleep(1)
except KeyboardInterrupt:
client.close()
logger.info("Client stopped")
if __name__ == "__main__":
main()
带指数退避的智能重连
import asyncio
import websockets
import random
import logging
logger = logging.getLogger(__name__)
class SmartReconnectWebSocket:
def __init__(self, uri, max_retries=10, base_delay=1, max_delay=60):
self.uri = uri
self.max_retries = max_retries
self.base_delay = base_delay
self.max_delay = max_delay
self.retry_count = 0
self.websocket = None
def get_backoff_time(self):
"""计算指数退避时间"""
delay = min(self.base_delay * (2 ** self.retry_count), self.max_delay)
# 添加随机抖动
jitter = random.uniform(0, delay * 0.1)
return delay + jitter
async def connect_with_retry(self):
"""带重试的连接"""
while self.retry_count < self.max_retries:
try:
self.websocket = await websockets.connect(
self.uri,
ping_interval=20,
ping_timeout=10,
close_timeout=5
)
logger.info(f"Connected successfully after {self.retry_count} retries")
self.retry_count = 0
return self.websocket
except Exception as e:
self.retry_count += 1
if self.retry_count >= self.max_retries:
logger.error(f"Max retries reached: {e}")
raise
backoff = self.get_backoff_time()
logger.warning(f"Connection failed (attempt {self.retry_count}): {e}")
logger.info(f"Retrying in {backoff:.2f} seconds")
await asyncio.sleep(backoff)
async def run(self, handler):
"""运行客户端"""
while True:
try:
async with await self.connect_with_retry() as ws:
logger.info("WebSocket connected")
await handler(ws)
except websockets.ConnectionClosed:
logger.warning("Connection closed, reconnecting...")
self.retry_count = 0
await asyncio.sleep(1)
except Exception as e:
logger.error(f"Unexpected error: {e}")
await asyncio.sleep(5)
# 使用示例
async def message_handler(websocket):
"""消息处理函数"""
async for message in websocket:
logger.info(f"Received: {message}")
# 处理消息
await websocket.send(f"Echo: {message}")
async def main():
client = SmartReconnectWebSocket(
uri="wss://echo.websocket.org",
max_retries=10,
base_delay=1
)
await client.run(message_handler)
if __name__ == "__main__":
asyncio.run(main())
- 自动重连:连接断开后自动尝试重新连接
- 重连策略:支持固定间隔、指数退避等多种重连策略
- 连接状态监控:实时监控连接状态
- 消息队列:支持断线期间消息的缓存和重发
- 心跳保活:可选的心跳机制保持连接活跃
选择方案时,考虑以下因素:
- websockets 库:适合 asyncio 异步编程
- websocket-client 库:适合回调式同步编程
- 性能要求:高并发场景建议使用异步方案
- 重连策略:指数退避适合生产环境
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播