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

Python Socket转发场景下第二次连接服务端触发Connection refused错误求助

问题根因定位
  • 服务端逻辑缺失TCP服务的核心运行流程,第一次客户端连接处理完成后,整个服务进程就直接退出,对应端口没有进程持续监听新连接。
  • 这完全匹配你遇到的异常现象:第一次连接时服务进程还在运行,能正常完成收发流程;第一次连接的客户端主动关闭socket后,服务端触发连接断开逻辑,直接退出程序,内核在收到第二次连接请求时,因为端口没有监听进程,直接返回连接拒绝,就触发了ConnectionRefusedError: [Errno 111] Connection refused。
现有代码的具体问题拆解
  • 完整TCP服务端必须满足的基础逻辑:预创建的监听socket要通过外层无限循环持续调用accept()方法,每接收一个新的客户端连接请求,拿到对应的已连接套接字后,再单独处理这个连接的收发逻辑;单个连接处理完成后,必须回到监听套接字的accept()步骤,等待下一个新连接。你当前的代码仅调用了一次accept(),拿到第一个客户端的连接套接字后就全程处理这一个连接,完全缺失外层的监听循环。
  • 异常处理逻辑存在缺陷:
    • 仅捕获了recv()方法触发的ConnectionResetError,如果捕获异常时data保留了之前的旧值,后续执行sendall()时会向已经断开的连接发送数据,触发未捕获的BrokenPipeError,直接导致服务端崩溃退出。
    • 当recv()返回空字符串(代表客户端正常断开连接)时,直接执行break跳出当前循环,没有任何代码能回到监听逻辑等待新连接。
  • 你把已连接套接字csockid放在最外层的with语句块中,当这个连接的处理逻辑结束时,块执行完成会自动退出,没有任何后续逻辑能接住新的连接请求。
修复方案
  • 调整服务端的循环结构,拆分为两层独立的执行逻辑:
    1. 外层无限循环用预创建的监听socket持续调用accept(),等待新的客户端连接
    2. 内层循环专门处理当前已建立连接的收发逻辑,连接断开后关闭当前连接的套接字,回到外层循环继续等待下一个连接
  • 扩大异常捕获范围,把sendall()可能触发的连接断开异常也纳入捕获逻辑,避免服务端因为未捕获的异常直接崩溃
  • 连接断开时仅关闭当前客户端的连接套接字,不能触发整个服务进程的退出

修正后的服务端参考代码:

# 预创建的监听socket,提前完成bind、listen操作,全程不手动关闭
while True:
    # 外层循环:持续等待新的客户端连接
    csockid, client_addr = listen_sock.accept()
    try:
        # 内层循环:处理当前连接的收发逻辑
        while True:
            try:
                data = csockid.recv(512)
                # 收到空数据代表客户端正常断开连接
                if not data:
                    break
                data = data.decode('utf-8').strip()
                csockid.sendall(data.encode('utf-8'))
            except (ConnectionResetError, BrokenPipeError):
                # 捕获连接断开类的异常,避免服务端崩溃
                break
    finally:
        # 无论正常断开还是异常断开,都关闭当前连接的套接字
        csockid.close()

内容的提问来源于stack exchange,提问作者h1smajesty

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 09:54:04