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

使用Socket与Threading搭建聊天室:客户端连接后服务器停止运行

问题排查与修复方案

服务器端(server.py)核心问题及修复

  1. 未定义变量触发崩溃
    代码中定义了存储客户端连接的列表client_conns,但新客户端连接时却调用了clients.append(conn),clients变量未定义,直接触发NameError导致服务器终止运行。

  2. 使用废弃的线程创建接口
    threading._start_new_thread是Python已废弃的底层线程接口,稳定性差,推荐使用标准的threading.Thread类创建线程。

  3. 未处理客户端断开场景
    客户端断开时,conn.recv()会返回空字节串,若不处理会导致后续广播报错,需及时将异常连接从列表移除并关闭。

  4. 广播未做异常捕获
    部分客户端连接异常时,直接调用conn.send()会抛出错误中断广播流程,需添加异常处理保证广播正常执行。

修复后的server.py代码:

import socket
import threading

host = socket.gethostbyname(socket.gethostname())
port = 5000
client_conns = []

s = socket.socket()
s.bind((host, port))
s.listen(10)

def broadcast_msg(msg, sender_conn):
    for conn in client_conns:
        # 广播时排除消息发送者
        if conn != sender_conn:
            try:
                conn.send(msg)
            except:
                # 移除异常连接并关闭
                client_conns.remove(conn)
                conn.close()

def handle_client(conn, addr):
    while True:
        try:
            msg = conn.recv(4096)
            if not msg:
                # 客户端主动断开
                client_conns.remove(conn)
                conn.close()
                print(f"Connection closed: {addr}")
                break
            broadcast_msg(msg, conn)
        except:
            # 处理连接异常
            client_conns.remove(conn)
            conn.close()
            print(f"Connection error: {addr}")
            break

while True:
    conn, address = s.accept()
    print(f"Connection from: {address}")
    client_conns.append(conn)

    # 使用标准线程创建方式
    thread = threading.Thread(target=handle_client, args=(conn, address))
    thread.start()

客户端(client.py)问题及修复

原客户端发送消息后会阻塞在recv(),因为服务器广播不会发给消息发送者。修改后用单独线程处理消息接收,避免输入卡顿:

修复后的client.py代码:

import socket
import threading

def receive_messages(s):
    while True:
        try:
            data = s.recv(4096).decode()
            if data:
                print("\n" + data)
        except:
            print("Connection closed")
            s.close()
            break

def client():
    host = socket.gethostbyname(socket.gethostname())
    port = 5000

    s = socket.socket()
    s.connect((host, port))

    alias = input("Alias: ")
    # 启动独立线程接收消息,避免阻塞输入
    receive_thread = threading.Thread(target=receive_messages, args=(s,))
    receive_thread.start()

    while True:
        message = input(f"{alias}: ")
        if message.lower() == 'quit':
            s.close()
            break
        message = alias + ": " + message
        s.send(message.encode())

client()

关键修复说明

  • 服务器端修正变量名错误,改用标准线程API,添加连接异常处理与断开清理逻辑
  • 客户端新增消息接收线程,解决输入阻塞问题,增加退出命令

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 01:23:30