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

Java在线象棋游戏多服务器部署:第三个玩家无法连接服务器问题求助

问题分析与解决方案

看起来你的问题出在服务端处理满员后的逻辑上,导致第三个玩家的客户端连接请求被阻塞,进而无法启动GUI窗口。让我拆解一下:

核心问题

当第一个游戏服务器(端口1001)接纳了2名玩家后,acceptConnections方法里的while (numPlayers < maxPlayers)循环会退出,此时服务器虽然不再调用ss.accept()来处理新连接,但没有关闭ServerSocket。这会导致后续客户端尝试连接这个端口时,操作系统会把连接请求挂起,客户端的Socket构造函数会一直处于阻塞状态,永远执行不到后面的pf.GUI()调用,所以窗口弹不出来。

修复步骤

1. 服务端:满员后关闭ServerSocket

在acceptConnections方法的循环结束后,添加关闭ServerSocket的代码,这样后续连接请求会直接被拒绝,客户端就能继续尝试其他可用端口:

public void acceptConnections(){
    try {
        System.out.println("Waiting for connections...");
        while (numPlayers < maxPlayers) {
            Socket s = ss.accept();
            DataInputStream in = new DataInputStream(s.getInputStream());
            DataOutputStream out = new DataOutputStream(s.getOutputStream());
            numPlayers++;
            out.writeInt(numPlayers);
            System.out.println("Player Number "+numPlayers+" has connected");
            ReadFromClient rfc = new ReadFromClient(numPlayers,in);
            WriteToClient wtc = new WriteToClient(numPlayers,out);
            if(numPlayers == 1){
                socket1 = s;
                p1read = rfc;
                p1write = wtc;
                Thread read1 = new Thread(p1read);
                Thread write1 = new Thread(p1write);
                read1.start();
                write1.start();
            } else{
                socket2 = s;
                p2read = rfc;
                p2write = wtc;
                Thread read2 = new Thread(p2read);
                Thread write2 = new Thread(p2write);
                read2.start();
                write2.start();
            }
        } // end of while
        System.out.println("No longer accepting connections");
        // 新增:关闭ServerSocket,拒绝后续连接请求
        ss.close();
    } catch(IOException e) {
        System.out.println("ERROR at: acceptConnections");
    }
}

2. 客户端:优化连接失败的提示(可选)

可以在connectToServer的循环结束后,添加一个提示,告诉用户所有服务器都满员了,避免无提示的情况,同时用更清晰的break替代i=4:

public void connectToServer(){
    boolean connected = false;
    for (int i = 1;i <=3 ;i++ ) {
        try {
            socket = new Socket("localhost",(1000+i));
            DataInputStream in = new DataInputStream(socket.getInputStream());
            DataOutputStream out = new DataOutputStream(socket.getOutputStream());
            PlayerID = in.readInt();
            System.out.println("You are Player Number:"+PlayerID);
            if(PlayerID == 1){
                System.out.println("Waiting for Oponent...");
            }
            rfs = new ReadFromServer(in);
            wts = new WriteToServer(out);
            Thread rT = new Thread(rfs);
            Thread wT = new Thread(wts);
            rT.start();
            wT.start();
            connected = true;
            break; // 替代i=4,逻辑更清晰
        } catch(IOException e) {
            System.out.println("Failed to connect to server on port "+(1000+i)+", trying next...");
        }
    }
    if(!connected){
        System.out.println("All game servers are full!");
    }
}

其他潜在优化点

  • 服务端的GameServer无参构造里,创建gs数组时,其实每个带参构造的GameServer实例不需要gs属性(因为只有无参构造用到它),可以考虑拆分代码,把多服务器管理的逻辑和单个游戏服务器的逻辑分开,让代码更清晰。
  • 客户端和服务端的线程逻辑可以增加异常处理的粒度,避免单个线程崩溃影响整个游戏进程。

这样修改后,第三个玩家连接第一个满员的服务器时会收到连接失败的异常,然后自动尝试第二个服务器(端口1002),就能成功连接并弹出GUI窗口了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 16:03:13