You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 21:18:11