多线程 Java 服务器设置
我正在尝试编写一个支持网络多人游戏的游戏服务器。
我试图实现的是一个服务器,它循环监听连接并为每个客户端设置一个线程。它应该执行此操作,直到游戏主机单击开始游戏,然后它应该继续游戏逻辑、发送数据等。
为了实现此目的,我在此线程的 run 方法中使用此代码来循环并侦听连接。
try {
while (gameStarted == false) {
System.out.print(gameStarted);
clientSocket = ss.accept();
ClientThreadOnServer runClient = new ClientThreadOnServer(clientSocket);
clientThreads.add(runClient);
window.updateText();
}
System.out.println("end");
然后,在我的服务器中,我放置了一个可运行的内部类,该类会弹出一个带有计数器和开始按钮的 JFrame,其想法是,当用户单击框架中的开始游戏时,布尔值 gameStarted 会被翻转,如下所示:
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("start")) {
synchronized (this) {
System.out.println("click");
gameStarted = true;
}
}
}
但是它没有工作!当您单击开始时,会检测到并按下按钮,因此布尔值可能会更改,但服务器不会退出 while 循环并继续。我想我知道为什么,循环位于 ss.accept();并且没有像我希望的那样测试布尔条件。
我不确定我是否以正确的方式处理这个问题,尤其是服务器上的客户端线程列表,我希望用它来控制数据的发送。如果我以完全错误的方式这样做,请让我知道应该如何完成,或者如果我没有疯,我该如何让我的代码工作?
I am trying to write a game server that supports multiplayer over a network.
What I am attempting to achieve is a server that listens in a loop for connections and sets up a thread for each client. it should do this until the host of the game clicks start game, upon which it should continue with the game logic, sending data etc.
To achieve this I use this code in the run method of this thread to loop and listen for connections.
try {
while (gameStarted == false) {
System.out.print(gameStarted);
clientSocket = ss.accept();
ClientThreadOnServer runClient = new ClientThreadOnServer(clientSocket);
clientThreads.add(runClient);
window.updateText();
}
System.out.println("end");
Within my server I then placed an runnable inner class that pops up a JFrame with a counter and a start button, with the idea being the boolean gameStarted gets flipped when the user clicks start game in the frame, like so:
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("start")) {
synchronized (this) {
System.out.println("click");
gameStarted = true;
}
}
}
however it doesn't work! When you click start the button is detected and pressed so presumably the boolean is changed, but the server doesn't exit the while loop and continue on. I think I know why, the loop is sitting on ss.accept(); and not testing the boolean condition as I had hoped.
I'm not really sure if I am even going about this in the right way, especially the list of client threads on the server which I hope to then use to control the sending of data. If I am doing this in a totally wrong way please let me know how it should be done, or if I am not crazy, how do I make my code work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这意味着循环只会在客户端连接后立即检查游戏状态。您可以使用
setTimeout()
指定在抛出SocketTimeoutException
表示客户端未连接之前,accept 调用可以阻塞多长时间。您可以在循环中使用它来使accept()
不会永远阻塞,并允许您再次检查gameStarted
。注:
您并未在
gameStarted
上完全同步,只是在写入时完全同步。这意味着存在竞争条件,您可能会在单击开始后尝试接受其他客户端。解决此问题的最简单方法是使用以下方法。您不想将整个循环放入同步块中,因为这样开始按钮将永远无法进入其同步块,因为循环保持锁定。This means that the loop will only check the game state right after a client has connected. You can use
setTimeout()
to specify the how long an accept call can block for before throwing aSocketTimeoutException
to signify that a client did not connect. You can use that in your loop to causeaccept()
to not block forever and allow you to checkgameStarted
again.Note:
You are not fully synchronizing on
gameStarted
, just on the write. This means there is a race condition and you might attempt to accept an additional client after start is clicked. The easiest way to fix this is with the following. You don't want to put the entire loop in a synchronized block because then the start button would never be able to enter it's synchronized block because the loop is holding the lock.