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

Java多人桌游:Client2发消息时BufferedReader阻塞无响应

问题:双客户端连接后服务器无法获取第二客户端的移动指令

当2个客户端连接服务器后游戏自动启动,服务器先等待Client1输入,回合切换后进入等待Client2输入的状态,但此时服务器无法获取Client2发送的移动指令。

服务器端代码片段

private ServerSocket socket;
private ServerTUI view;
private ServerLogic serverLogic;
private int readyCounter;
private final List<ClientHandler> clients = new ArrayList<ClientHandler>();
private boolean madeMove = false;
private int next_client_no;

public Server() {
    view = new ServerTUI();
    next_client_no = 1;
    readyCounter=0;
}

public void run() {
    boolean openNewSocket = true;
    while (openNewSocket) {
        try {
            setup();

            while (true) {
                Socket sock = socket.accept();
                ClientHandler handler = new ClientHandler(sock, this);
                synchronized (clients) {
                    clients.add(handler);
                }
                new Thread(handler).start();
                String name = "Client " + String.format("%02d", next_client_no++);
                view.showMessage("New client [" + name + "] connected!");
            }
        } catch (Exception e) {
            openNewSocket = false;
        }
    }
}

public synchronized void playGame() throws ServerUnavailableException, IOException {
    Player current = null;
    while (!serverLogic.isGameOver(serverLogic.getPlayers().get(serverLogic.getCurrentPlayer()).getRack())) {
        madeMove = false;
        current = serverLogic.getPlayers().get(serverLogic.getCurrentPlayer());
        getServerLogic().setCopyRack(current.getRack());
        getServerLogic().setCopyBoard(getServerLogic().getBoard());
        // 等待输入
        while (!madeMove) {
        }
        changeTurn();
    }
}

服务器端ClientHandler代码

public class ClientHandler implements Runnable{
    private BufferedReader in;
    private BufferedWriter out;
    private Socket sock;
    private Player player;
    private Server srv;
    private String name;

    public ClientHandler(Socket sock, Server srv){
        try {
            this.sock = sock;
            this.srv = srv;
            in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
            out = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
        } catch (IOException e) {
            shutdown();
        }
    }
    public void run() {
        try {
            String msg;

            while ((msg = in.readLine()) != null) { // 此处似乎卡住
                handleCommand(msg); // 从这里处理指令
            }
            shutdown();
        } catch (IOException | ServerUnavailableException e) {
            shutdown();
        }
    }
    public synchronized void sendMessage(String message) throws ServerUnavailableException {
        if (out != null) {
            try {
                out.write(message);
                out.newLine();
                out.flush();
            } catch (IOException e) {
                throw new ServerUnavailableException("无法向客户端发送消息: " + e.getMessage());
            }
        }
    }
}

客户端代码片段

public class Client implements Runnable {
    @Override
    public void run() {
        try {
            String command;
            while (serverSock.isConnected()) {
                command = in.readLine();
                processCommand(command);
            }
        } catch (IOException | ProtocolException e) {
            throw new RuntimeException(e);
        }
    }
    public void startClient() {
        startConnection();
    }

    public void startConnection() {
        // 待实现
        boolean connected = false;
        while (!connected) {
            try {
                createConnection();
                name = view.getString("请输入用户名");
                if (Protocol.isValidName(name)) {
                    handleHello();
                } else {
                    System.out.println("请输入合法的用户名");
                    break;
                }
                connected = true;
                Thread listenerThread = new Thread(this);
                listenerThread.start();
            } catch (ExitProgram e) {
                view.showMessage("正在退出程序...");
                break;
            } catch (ServerUnavailableException e) {
                view.showMessage("连接失败: " + e.getMessage());
                if (!view.getBoolean("是否重试?")) {
                    break;
                }
            } catch (ProtocolException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public synchronized void sendMessage(String msg)
            throws ServerUnavailableException {
        if (out != null) {
            try {
                out.write(msg);
                out.newLine();
                out.flush();
            } catch (IOException e) {
                view.showMessage(e.getMessage());
                throw new ServerUnavailableException("无法向服务器写入消息: " + msg);
            }
        } else {
            throw new ServerUnavailableException("无法向服务器写入消息: " + msg);
        }
    }
}

已尝试的解决方法

  • 逐步调试,但多线程和双客户端环境下存在异常行为
  • 将sendMessage独立为单独类,多种方案均未解决问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 16:54:51