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

如何检测Socket是否仍连接?解决客户端断开后服务器异常循环问题

问题分析与解决方案

首先你的代码存在几个基础问题需要先修正:

  • s.listen(10)应该放在accept()之前,只需调用一次,不需要放到循环里
  • 代码使用了time.sleep()但未导入time模块,会触发报错
  • 当前逻辑未检测客户端连接状态,导致客户端断开后循环仍持续执行

检测客户端断开的核心逻辑

TCP连接中,判断客户端是否断开主要依赖两种场景:

  1. recv()返回空字节串:当客户端主动调用close()断开连接时,服务器端的recv()会返回b''
  2. 捕获连接异常:如果客户端异常断开(比如强制关闭进程),调用recv()或send()时会抛出ConnectionResetError类异常

修正后的完整代码

import socket
import time

ip = '127.0.0.1'  # 修正无效回环地址,127.1.0.0无法正常监听
port = 2400

# 创建socket并完成绑定
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((ip, port))
s.listen(10)  # listen仅需调用一次

print(f"服务器已启动,等待客户端连接...")

while True:
    # 等待新客户端接入
    clientsocket, address = s.accept()
    print(f"客户端 {address[0]}:{address[1]} 已连接")

    # 处理当前客户端的消息循环
    try:
        while True:
            msg = clientsocket.recv(8196)
            # 判断客户端主动断开
            if not msg:
                print(f"客户端 {address[0]}:{address[1]} 主动断开连接")
                break
            print(f"收到 {address[0]}:{address[1]} 的消息: {msg.decode()}\n")
            time.sleep(0.05)
    except ConnectionResetError:
        print(f"客户端 {address[0]}:{address[1]} 异常断开连接")
    finally:
        # 无论正常/异常断开,都关闭客户端socket
        clientsocket.close()
        print(f"已关闭与 {address[0]}:{address[1]} 的连接")

关键说明

  • 采用两层循环结构:外层循环等待新客户端连接,内层循环处理当前客户端的消息交互
  • 通过if not msg直接判断客户端主动断开的情况,这是TCP协议原生的断开通知机制
  • 用try-except捕获客户端异常断开的场景,确保socket能被正常关闭
  • 修正了回环地址的错误,127.1.0.0不是有效的回环地址,改为127.0.0.1才能正常监听

你之前尝试用send()检测连接的问题,大概率是误用了服务器主sockets而非客户端的clientsocket,且盲目发送可能触发不必要的异常。优先通过recv()返回值判断是更可靠的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 05:37:09