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

多客户端socket服务端仅单个客户端可接收result函数消息问题咨询

多客户端Socket消息推送问题排查与修复方案

问题产生原因

  • 服务端推送逻辑仅支持单连接发送:每个客户端对应独立的ServerThread线程,result函数接收的connectionSocket是当前线程绑定的单个客户端连接,调用send只会给这一个客户端发消息,没有实现全量广播逻辑。
  • 缺少全局客户端连接管理:没有统一存储所有在线客户端的socket列表,无法遍历所有连接批量推送结果。同时全局的guess_box没有加线程锁,多线程并发写入时可能出现竞态问题,导致数组长度异常。
  • 结果推送逻辑重复执行风险:两个客户端线程都在等待guess_box长度变为2,满足条件后两个线程都会调用result函数,会出现重复推送的问题,且原有result逻辑没有区分当前连接对应的玩家身份,推送的消息可能和玩家身份不匹配。
  • 客户端接收逻辑缺陷:原有逻辑中客户端正确提交guess后,仅调用一次recv就退出循环,后续即使服务端推送了结果,客户端也不会再执行接收逻辑。同时服务端TF函数仅在输入错误时返回响应,正确提交时无返回,会导致客户端提交后卡在recv步骤。

修复方案

服务端修改

  1. 新增全局资源管理变量,用于存储客户端连接、加锁避免并发问题:
import threading
# 原有全局变量基础上新增
client_sockets = []
lock = threading.Lock()
result_sent = False
# 新客户端接入时,将对应socket加入client_sockets列表,客户端断开连接时从列表中移除
  1. 修改TF函数,提交正确时给客户端返回响应,避免客户端卡住:
def TF(connectionSocket, var, guess_box, addr, addr_l):
    msg = connectionSocket.recv(1024).decode()
    print("recv:",msg)
    if msg == 'true' or msg == 'false':
        var = str(var)
        res_bool = bool(msg.capitalize() == var)
        guess_box.append(res_bool)
        # 新增提交成功响应
        connectionSocket.send("Submit success, waiting for another player...".encode())
        return 'ok'
    else:
        print(msg)
        statement = "4002 Unrecognized message!!"
        connectionSocket.send(statement.encode())
        return 'again'
  1. 修改result函数为广播逻辑,给所有在线客户端推送结果:
def result(guess_box, guess):
    if guess_box[0] == guess_box[1]:
        msg = "Tie!!"
    elif guess_box[0] == guess:
        msg = "Player 1 Wins!"
    else:
        msg = "Player 2 Wins!"
    # 加锁遍历所有客户端发送,避免并发异常
    with lock:
        for sock in client_sockets:
            try:
                sock.send(msg.encode())
            except:
                # 发送失败说明客户端已断开,直接移除
                client_sockets.remove(sock)
    return '2'
  1. 修改ServerThread的运行逻辑,避免重复推送结果:
class ServerThread(threading.Thread):
    def __init__(self, client):
        threading.Thread.__init__(self)
        self.client = client

    def run(self):
        # ... 原有连接初始化逻辑
        print("guess is:", guess)
        while len(guess_box) != 2:
            with lock:
                TF(connectionSocket, guess, guess_box, addr, addr_l)
        print("start")
        # 仅第一个跳出循环的线程执行推送逻辑
        with lock:
            if not result_sent:
                result(guess_box, guess)
                result_sent = True
        # ... 原有连接关闭逻辑

客户端修改

调整PlayGame函数的接收逻辑,提交成功后先收提交响应,再收最终比赛结果再退出:

def PlayGame(clientSocket, msg):
    invalid = "NO!"
    if "/guess " in msg:
        msg1 = msg.split(" ")[1]
        print("Hi1\n")
        if msg1 == "true" or msg1 == "false":
            print("Hi11")
            clientSocket.send(msg1.encode())
            # 接收提交成功响应
            print(clientSocket.recv(1024).decode())
            # 接收最终比赛结果
            print(clientSocket.recv(1024).decode())
            print("!")
            return '1'
        else:
            clientSocket.send(invalid.encode())
            print(clientSocket.recv(1024).decode())
            print("2")
            return '2'
    elif msg == "":
        return '2'
    else:
        clientSocket.send(invalid.encode())
        print(clientSocket.recv(1024).decode())
        print("3")
        return '2'

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 22:24:02