为了实现在 on_close 回调中重新连接的功能,我们可以利用 aiohttp 的 WebSocket 功能,并结合异步任务来实现自动重连。以下是一个示例代码,展示了如何在 on_close 回调中重新连接。
示例代码
import asyncio
import aiohttp
import logging
logging.basicConfig(level=logging.INFO)
async def on_message(message):
logging.info(f"Received message: {message}")
async def on_close(session, url):
logging.warning("WebSocket connection closed. Attempting to reconnect.")
await safe_connect(session, url)
async def safe_connect(session, url, max_retries=5):
retries = 0
while True:
try:
async with session.ws_connect(url) as ws:
logging.info("Connected to WebSocket server.")
async for msg in ws:
if msg.type == aiohttp.WSMsgType.TEXT:
await on_message(msg.data)
elif msg.type == aiohttp.WSMsgType.CLOSED:
break
elif msg.type == aiohttp.WSMsgType.ERROR:
logging.error(f"WebSocket error: {ws.exception()}")
break
except (aiohttp.ClientConnectionError, aiohttp.ServerDisconnectedError, asyncio.TimeoutError) as e:
retries += 1
if retries >= max_retries:
raise Exception(f"Max retries ({max_retries}) exceeded for {url}") from e
logging.warning(f"Retrying ({retries}/{max_retries}): {e}")
await asyncio.sleep(2 ** retries) # Exponential backoff
finally:
await on_close(session, url)
async def main():
url = 'wss://api.example.com/ws'
async with aiohttp.ClientSession() as session:
await safe_connect(session, url)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
代码解释
-
导入必要的模块
import asyncio import aiohttp import logging logging.basicConfig(level=logging.INFO) -
定义消息处理函数
async def on_message(message): logging.info(f"Received message: {message}") -
定义连接关闭回调函数
async def on_close(session, url): logging.warning("WebSocket connection closed. Attempting to reconnect.") await safe_connect(session, url) -
定义带有重试逻辑的安全连接函数
async def safe_connect(session, url, max_retries=5): retries = 0 while True: try: async with session.ws_connect(url) as ws: logging.info("Connected to WebSocket server.") async for msg in ws: if msg.type == aiohttp.WSMsgType.TEXT: await on_message(msg.data) elif msg.type == aiohttp.WSMsgType.CLOSED: break elif msg.type == aiohttp.WSMsgType.ERROR: logging.error(f"WebSocket error: {ws.exception()}") break except (aiohttp.ClientConnectionError, aiohttp.ServerDisconnectedError, asyncio.TimeoutError) as e: retries += 1 if retries >= max_retries: raise Exception(f"Max retries ({max_retries}) exceeded for {url}") from e logging.warning(f"Retrying ({retries}/{max_retries}): {e}") await asyncio.sleep(2 ** retries) # Exponential backoff finally: await on_close(session, url) -
定义主函数
async def main(): url = 'wss://api.example.com/ws' async with aiohttp.ClientSession() as session: await safe_connect(session, url) -
启动事件循环
if __name__ == '__main__': loop = asyncio.get_event_loop() loop.run_until_complete(main())
注意事项
- 指数退避策略: 在每次重试之间增加等待时间,以减少对服务器的压力。
- 最大重试次数: 防止无限重试导致程序挂起。
- 日志记录: 记录重试和失败的信息,便于调试和监控。
通过这种方式,可以在 on_close 回调中重新连接 WebSocket 连接,从而实现更可靠的通信。希望这对您有所帮助!如果有任何进一步的问题,请随时提问。


被折叠的 条评论
为什么被折叠?



