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
相关产品推荐
相关产品推荐

