如何在Java中关闭一个线程?

时间:2010-02-19 21:00:18

标签: java multithreading sockets

我是Java的新手,我正在尝试修改套接字服务器的示例以支持基于闪存的游戏。要允许闪存连接到服务器,我需要提供策略文件。

我之前从未编写过服务器应用程序,所以我不太熟悉需要发生的事情。

无论如何,我已经做到了它输出文件,但由于某种原因,它会这样做10次。

我需要在继续再次执行之前关闭该线程。下面是我的代码,注释我需要关闭该线程。

import java.io.*;
import java.net.*;
import java.util.Random;

public class Main {

  private static int port=4041, maxConnections=0;
  // Listen for incoming connections and handle them
  public static void main(String[] args) {
    int i=0;

    try{
      ServerSocket listener = new ServerSocket(port);
      Socket server;

      while((i++ < maxConnections) || (maxConnections == 0)){
        doComms connection;

        server = listener.accept();
        doComms conn_c= new doComms(server);
        Thread t = new Thread(conn_c);
        t.start();
      }
    } catch (IOException ioe) {
      System.out.println("IOException on socket listen: " + ioe);
      ioe.printStackTrace();
    }
  }

}

class doComms implements Runnable {
    private Socket server;
    private String line,input;

    doComms(Socket server) {
      this.server=server;
    }

    public void run () {

        char EOF = (char)0x00;
      input="";

      try {
        // Get input from the client
        DataInputStream in = new DataInputStream (server.getInputStream());
        PrintStream out = new PrintStream(server.getOutputStream());

        while((line = in.readLine()) != null && !line.equals(".")) {
          input=input + line;
          if(line.trim().equals("h")){

              out.println("h"+EOF);

          }
          else if(line.trim().equals("i")){

               Random randomGenerator = new Random();
               int randomInt = randomGenerator.nextInt(4);

              out.println("b"+randomInt+EOF);


          }
          else if(line.trim().equals("c")){ System.out.println("Player collision.");}
          else if (line.trim().equals("<policy-file-request/>")) {
            out.println("<?xml version=\"1.0\"?>\n<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\"><cross-domain-policy>\n<site-control permitted-cross-domain-policies=\"all\"/>\n<allow-access-from domain=\"*\"/>\n</cross-domain-policy>"+EOF);
            System.out.println("Responded to policy request");
            // I need to close the thread / disconnect the client here.
          }
          else System.out.println("Unknown command: "+line.trim());

        }
        server.close();
      } catch (IOException ioe) {
        System.out.println("IOException on socket listen: " + ioe);
        ioe.printStackTrace();
      }
    }
}

另外,在NetBeans中,它还有一个额外的东西,它强调“import java.io. *;”并说不正确的包装,但它仍然可以正常工作。

修改 我已经知道它发送10次的原因是它在一次发送操作中接收10行。我试过添加一个“返回”;在它发送策略XML的地方,但它似乎仍然没有d / c客户端。我还要注意,我打算将它作为一个多人游戏服务器,所以我需要保持套接字打开并关闭一个线程。

4 个答案:

答案 0 :(得分:3)

乍一看,您的run()方法看起来应该正常终止。我怀疑你的循环:

while((i++ < maxConnections) || (maxConnections == 0)){

由于maxConnections被初始化为0并且永远不会增加,所以循环似乎无限运行并创建了许多线程 - 可能与套接字可以接受侦听器一样多。然后它以IOException从循环中突然出现。这是真正发生的事吗?

更新:显然不是......现在没有想法。

答案 1 :(得分:0)

您的代码很有意义。你的意见是什么?如果你有10行说“&lt; policy-file-request /&gt;” ,然后它确实会打印文件10次。那你所有的其他条款怎么样?在每一个你打印的东西+ EOF,但你肯定只想打印一个响应每个请求。您的“输入”变量也未使用。

答案 2 :(得分:0)

从doComms.run()返回后线程将死亡。请将Java中类名的开头大写:它应该是DoComms,只是为了让其他Java程序员更容易理解代码。

要关闭连接,您对server.close()的通话应该会这样做。要确保首先完全发送输出,您应在致电close()之前致电flush()PrintStream

您发送了什么输入?看起来如果您只从客户端发送一次Socket.close(),您只能获得一次文件。

不确定NetBeans,但它是否抱怨您<policy-file-request/>文件的顶部没有指定package?尝试添加以下包声明,其中包含相对于NetBeans项目顶部的路径:

.java

答案 3 :(得分:0)

我建议在调试器中运行服务器和客户端,然后单步执行以查看每个时间点发生的情况。这将帮助您确认每个点的预期值。 Eclipse和其他Java IDE具有相当不错(且易于使用)的调试器。

至于你的代码:

  1. 我会为每个人做一次line.trim() 循环迭代,而不是 修剪()反复和 不必要地创造额外的 对象。
  2. 确保客户端和服务器在每个请求/响应之后都刷新()套接字的OutputStream。如果套接字的OutputStream尚未刷新,则连接另一端的InputStream可能阻塞等待输入,而OutputStream则阻塞等待填充其缓冲区。
  3. 客户端中的代码是什么 看起来像?你确定吗? 发送空或“。”关闭 连接?在检查“。”之前是否需要修剪()
  4. 正如其他人所提到的,您的代码不遵循典型的Java编码约定。我建议您阅读已发布的code conventions for Java
  5. ,以加快速度