【问题标题】:Multi-Threaded Java Server setp多线程 Java 服务器设置
【发布时间】:2011-04-07 23:40:29
【问题描述】:

我正在尝试编写一个支持网络多人游戏的游戏服务器。

我试图实现的是一个服务器,它在循环中侦听连接并为每个客户端设置一个线程。它应该这样做,直到游戏主机点击开始游戏,然后它应该继续游戏逻辑,发送数据等。

为了实现这一点,我在这个线程的 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();并且没有像我希望的那样测试布尔条件。

我不确定我是否以正确的方式处理这件事,尤其是服务器上的客户端线程列表,我希望随后使用它来控制数据的发送。如果我以完全错误的方式执行此操作,请告诉我应该如何完成,或者如果我不疯狂,我该如何让我的代码工作?

【问题讨论】:

  • while (gameStarted == false) { -> while (!gameStarted) { 不是答案,只是风格。
  • 不,不幸的是没有任何区别,但谢谢
  • 对不起,我意识到我的评论并不完全清楚。你在我编辑之前回复了它。

标签: java multithreading


【解决方案1】:

accept() -
监听连接 对这个套接字进行并接受 它。该方法阻塞,直到 建立连接。

这意味着循环只会在客户端连接后立即检查游戏状态。您可以使用setTimeout() 指定在抛出SocketTimeoutException 以表示客户端未连接之前可以阻塞多长时间。您可以在循环中使用它来使accept() 不会永远阻塞,并允许您再次检查gameStarted

注意:
您没有在gameStarted 上完全同步,只是在写入。这意味着存在竞争条件,您可能会在单击开始后尝试接受其他客户端。解决此问题的最简单方法是使用以下方法。您不想将整个循环放在同步块中,因为这样开始按钮将永远无法进入它的同步块,因为循环正在持有锁。

private synchronized boolean isGameStarted() {
  return gameStarted;
}

...
try {
  while (!isGameStarted()) {
...

【讨论】:

  • 您可能希望将 setTimeout() 更改为 setSoTimeout()。链接是正确的,但文本不正确,这可能会引起一些混淆。我会这样做,但非作者编辑必须至少有六个字符。
  • 所以我做了 ss.setSoTimeout(1000);在构造函数中,修复了 catch 并在循环内进行了 try/catch,它似乎正在工作,非常感谢!您将如何解决竞争条件,将整个循环保持在同步块中,或者有更好的方法吗?
猜你喜欢
  • 2019-05-27
  • 2015-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-27
  • 1970-01-01
相关资源
最近更新 更多