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

Java Socket游戏服务端如何等待所有客户端输入用户名后再广播消息

解决方案

调整思路

  • 移除原有连接数达标立即广播的逻辑,避免在玩家未完成用户名输入时提前发送开局消息
  • 在GameServer中新增线程安全的就绪玩家计数器,用于统计完成用户名输入的玩家数量
  • 每个玩家完成用户名输入后更新就绪计数,当计数达到最大玩家数阈值时,统一触发开局广播
  • 新增开局状态标记,避免多线程并发时重复触发广播

代码修改

1. GameServer.java 调整

首先新增2个成员变量,删除accept循环中的广播逻辑,新增玩家就绪回调方法:

import java.util.concurrent.atomic.AtomicInteger;

public class GameServer {
    // 原有成员变量保留:serverSocket、maxPlayers、playerThreads等
    private AtomicInteger readyPlayerCount = new AtomicInteger(0);
    private boolean gameStarted = false;

    // 原有其他方法保留,修改accept循环逻辑:
    public void start() throws IOException {
        while (true) {
            Socket clientSocket = serverSocket.accept();
            PlayerThread playerThread = new PlayerThread(clientSocket, this);
            playerThreads.add(playerThread);
            playerThread.start();
            // 删掉原来此处的连接数达标广播逻辑
        }
    }

    // 新增玩家就绪回调方法
    public synchronized void onPlayerReady() {
        int currentReady = readyPlayerCount.incrementAndGet();
        // 仅当所有玩家就绪且未开局时,触发广播
        if (currentReady == maxPlayers && !gameStarted) {
            gameStarted = true;
            broadcast("All players have joined! Let the game begin!", null);
        }
    }

    // 原有broadcast、addPlayer等方法保留
}

2. PlayerThread.java 调整

修正原有变量名笔误,在玩家完成用户名输入后调用就绪回调:

@Override
public void run() {
    try {
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        out = new PrintWriter(socket.getOutputStream(), true);
        out.println("What's your name? ");
        String userName = in.readLine();
        Player player = new Player(userName);
        gameServer.addPlayer(player);
        // 玩家输入完成,通知服务端已就绪
        gameServer.onPlayerReady();
        
        String clientMove;
        while ((clientMove = in.readLine()) != null) {
            gameServer.makeMove(player, clientMove);
            gameServer.broadcast(player.getName() + " made the move:  " + clientMove, this);
        }

    } catch (IOException e) {
        e.printStackTrace();
    }
}

说明

  • 使用AtomicInteger做就绪计数,保证多线程并发操作时计数的准确性,不会出现计数丢失问题
  • onPlayerReady方法加synchronized同步锁,配合gameStarted标志位,保证开局消息只会广播一次,不会出现重复发送的问题
  • 原有广播、玩家移动处理等逻辑无需修改,不影响后续游戏流程

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 05:54:04