你的服务器每次运行只支持一场比赛——你启动服务器,玩家连接,玩游戏,如果要开始另一场游戏,你必须杀死服务器并重新启动——因为 for 循环的编写方式。
while(true) {
playerOneSocket = welcomeSocket.accept(); // 1
playerTwoSocket = welcomeSocket.accept(); // 2
startNewMatch(playerOneSocket,playerTwoSocket);
}
public void startNewMatch(final Socket pOne, final Socket pTwo) {
new Thread(new Runnable() {
@Overrride
public void run() {
// pOne, pTwo variables visible here
}
}).start();
}
(任何)服务器必须始终可以自由地接受新请求,这就是为什么您在处理单个匹配逻辑的新线程中传递两个套接字的原因。startNewMatch 函数的参数已设置为 final,以便在 run 方法中看到,但您可能希望创建一个扩展 Thread 的新类并将它们传递给构造函数。希望有帮助。
编辑:
while 循环在您的主线程中运行,例如在内部:
public static void main(String[] args)
函数,并且您在每场比赛中启动一个新线程。您不希望每个玩家都在自己的线程中,因为这会浪费资源(请参阅 EDIT^3)并且编写这样的代码会更加繁重。看看下面的教程1 , 2 , 3
编辑^2:
“但我的困惑是服务器如何知道现在playerone正在通信以及玩家2何时通信......Bcz服务器对两个客户端都有相同的套接字。”
不,服务器总是在给定的端口上监听,并且每个请求都通过 accept 方法获得一个新的连接(端口)。
java API doc 是你最好的朋友——专门针对ServerSocket 接受它说:
侦听要与此套接字建立的连接并接受它。该方法阻塞,直到建立连接
那么,当
playerOneSocket = welcomeSocket.accept();
执行时,在 playerOneSocket 变量中,您已经建立了到播放器的“连接”(在服务器和播放器都知道的其他端口上),并且服务器可以接受同一端口上的另一个连接 - 第二个也是如此播放器。例如 1345 是您的游戏端口:
P1:连接@服务器:1345
接受方法开始 - 第 1 行
服务器:让我们在端口 9999 见面
P1:连接@服务器:9999
服务器:确定已连接
接受方法结束 - 第 1 行
P2:连接@服务器:1345
接受方法开始 - 第 2 行
服务器:让我们在端口 10000 见面
P2:连接@服务器:10000
服务器:确定已连接
接受方法结束 - 第 2 行
编辑^3:
我建议你这样做:首先,让它在每场比赛中使用一个线程,然后移动到每个玩家一个线程(如 Tudor 所示) - 游戏将在更大的网络延迟(例如通过 Internet)上响应更快。为了每个播放器模型执行一个线程,您需要了解良好的线程和线程通信 - 请参阅本教程