多客户端socket服务端仅单个客户端可接收result函数消息问题咨询
多客户端Socket消息推送问题排查与修复方案
问题产生原因
- 服务端推送逻辑仅支持单连接发送:每个客户端对应独立的
ServerThread线程,result函数接收的connectionSocket是当前线程绑定的单个客户端连接,调用send只会给这一个客户端发消息,没有实现全量广播逻辑。 - 缺少全局客户端连接管理:没有统一存储所有在线客户端的socket列表,无法遍历所有连接批量推送结果。同时全局的
guess_box没有加线程锁,多线程并发写入时可能出现竞态问题,导致数组长度异常。 - 结果推送逻辑重复执行风险:两个客户端线程都在等待
guess_box长度变为2,满足条件后两个线程都会调用result函数,会出现重复推送的问题,且原有result逻辑没有区分当前连接对应的玩家身份,推送的消息可能和玩家身份不匹配。 - 客户端接收逻辑缺陷:原有逻辑中客户端正确提交guess后,仅调用一次
recv就退出循环,后续即使服务端推送了结果,客户端也不会再执行接收逻辑。同时服务端TF函数仅在输入错误时返回响应,正确提交时无返回,会导致客户端提交后卡在recv步骤。
修复方案
服务端修改
- 新增全局资源管理变量,用于存储客户端连接、加锁避免并发问题:
import threading # 原有全局变量基础上新增 client_sockets = [] lock = threading.Lock() result_sent = False # 新客户端接入时,将对应socket加入client_sockets列表,客户端断开连接时从列表中移除
- 修改
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'
- 修改
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'
- 修改
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
相关产品推荐
相关产品推荐

