如何在asyncio Telnet客户端实现socket.send()异常时无限重连?
解决Telnet客户端自动重连问题
你的代码存在几个关键问题,导致无法捕获发送阶段的异常,也无法实现稳定的自动重连,以下是修复后的代码:
import asyncio valueTime = 3 async def telnet_client(host: str, port: int) -> None: while True: reader, writer = None, None try: # 尝试建立连接 reader, writer = await asyncio.open_connection(host, port) print(f"已连接到 ({host}, {port})") while True: # 写入数据到缓冲区 writer.write("hello\n".encode()) # 等待数据实际发送完成,连接异常会在此处触发 await writer.drain() # 使用异步sleep,避免阻塞整个事件循环 await asyncio.sleep(valueTime) except (ConnectionRefusedError, asyncio.IncompleteReadError, BrokenPipeError, OSError): # 捕获常见的通信类异常 print("通信异常,准备重连...") except Exception as e: # 处理其他未预期的异常 print(f"发生未知错误: {str(e)}") finally: # 确保连接资源被正确释放 if writer: writer.close() await writer.wait_closed() # 重连前添加延迟,避免高频重试 await asyncio.sleep(2) try: asyncio.run(telnet_client("192.168.1.126", 23)) except KeyboardInterrupt: print("客户端已退出")
核心修复说明:
- 替换
time.sleep为await asyncio.sleep:time.sleep会阻塞整个异步事件循环,导致异常触发延迟、其他任务停滞,异步环境必须使用专属的sleep方法。 - 添加
await writer.drain():writer.write仅将数据放入缓冲区,drain()会等待数据实际发送到服务端,此时连接断开才会抛出可捕获的异常。 - 精准捕获异常:不再使用裸
except,而是针对连接拒绝、管道破裂、IO错误等通信场景的异常做针对性捕获,同时保留通用异常处理兜底。 - 完善连接清理:在
finally块中确保关闭连接并等待资源释放,避免连接泄漏。 - 增加重连延迟:每次异常后等待2秒再重试,避免短时间内大量重试对服务端造成不必要的压力。
修改后,客户端在通信中断时会自动捕获异常、清理资源,随后尝试重新连接,实现无限自动重连的需求。
内容的提问来源于stack exchange,提问作者Roni Hacohen
相关产品推荐
相关产品推荐

