2012-06-03 96 views
2

因此,我正在Java中創建一個聊天服務器,以便根據Hamachi移出我的Minecraft服務器中的主機和通信。它完美的工作,除了一件事:我不知道如何我的生活如何添加命令到服務器。我的主循環去如下:帶命令的Java聊天服務器

/*Executed in constructor*/ 
public void listen(int port) throws IOException { 
    //Initialize the ServerSocket 
    ss = new ServerSocket(port); 
    System.out.println("Listening on " + InetAddress.getLocalHost() + ":" + ss.getLocalPort()); 

    running = true; 

    //Keep accepting connections 
    while (running) { 
     //Get the incoming connection 
     Socket s = ss.accept(); 
     System.out.println("Connection from: " + getFullIP(s)); 

     //Create a DataOutputStream for writing data to the other side 
     DataOutputStream dataOut = new DataOutputStream(s.getOutputStream()); 

     //Save this stream so I don't have to make it again 
     outputStreams.put(s, dataOut); 

     //Create a new thread for this connection 
     new ServerThread(this, s); 

     if (!running) { 
      stop(); 
     } 
     Scanner cmdScanner = new Scanner(System.in); 
     String command = cmdScanner.next(); 
     processCommand(command); 
    } 
} 

這段代碼的結果是,直到客戶端連接到(因爲ss.accept())的服務器我不能鍵入的命令。在執行命令之前,客戶端無法連接(cmdScanner.next())。我如何解決這個問題?

回答

1

我認爲你的命令處理器應該在另一個線程中。恕我直言,服務器應該總是有一個線程,只有工作是接收新的連接和調度它。處理你的輸入應該是其他線程的一部分。

public class TestThread 
{ 
    public static void main(String[] args) 
    { 
     new ConnectionDispatcher(8080).start(); 
     new CommandProcessor().start(); 
    } 
} 
class ConnectionDispatcher extends Thread{ 
    private int port; 
    private OutputStream outputStreams; 

    ConnectionDispatcher(int port) 
    { 
     this.port = port; 
    } 

    @Override 
    public void run() 
    { 
     try 
     { 
      listen(port); 
     } 
     catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public void listen(int port) throws IOException 
    { 
     //Initialize the ServerSocket 
     ss = new ServerSocket(port); 
     System.out.println("Listening on " + InetAddress.getLocalHost() + ":" + ss.getLocalPort()); 

     boolean running = true; 

     //Keep accepting connections 
     while (running) { 
      //Get the incoming connection 
      Socket s = ss.accept(); 
      System.out.println("Connection from: " + getFullIP(s)); 

      //Create a DataOutputStream for writing data to the other side 
      DataOutputStream dataOut = new DataOutputStream(s.getOutputStream()); 

      //Save this stream so I don't have to make it again 
      outputStreams.put(s, dataOut); 

      //Create a new thread for this connection 
      new ServerThread(this, s); 

     } 
    } 
} 

class CommandProcessor extends Thread{ 
    @Override 
    public void run() 
    { 
     Scanner cmdScanner = new Scanner(System.in); 
     String command = cmdScanner.next(); 
     processCommand(command); 
    } 
} 
+0

謝謝!你能給我一個關於這個過程的輪廓,或者指出我有一個好的方向嗎? – mattbdean

+0

哦!我明白你的意思了。非常感謝! – mattbdean

1

當我開始建立網絡時,我遇到了同樣的問題。你的線程在ss.accept()處停止,然後在代碼中不繼續。你需要實現另一個專用於你的ServerSocket的線程。這裏是一個例子:

public class Server implements Runnable 
{ 
    ServerSocket server; // the serverSock your clients will connect to 
    Thread thread; // the thread for your server 
    boolean running; // whether or not the server is running 

    public Server(int port) 
    { 
     running = false; // server is not yet running 
     connect(port); // setup server 
    } 

    public void connect(int port) 
    { 
     try 
     { 
      server = new ServerSocket(port); setup server on port 

      running = true; // server is running 
      thread = new Thread(this); // initialize server thread 
      thread.start(); // start thread 
     } catch(Exception e){e.printStackTrace(); running = false;} // port is in use 
    } 

    public void disconnect() 
    { 
     try 
     { 
      server.close(); 
     }catch(Exception e){e.printStackTrace();} 

     running = false; 
     thread = null; 
     server = null; 
    } 

    public void run() 
    { 
     while(running) 
     { 
      Socket client = server.accept(); // client connects to server 
      // handle the client... 
      ClientHandler handler = new ClientHandler(client); 
     } 
    } 

    public class ClientHandler implements Runnable 
    { 
     Thread clientThread; 
     DataOutputStream out; 

     public ClientHandler(Socket socket) 
     { 
      out = new DataOutputStream(socket.getOutputStream());//setup the output stream 
      clientThread = new Thread(this); // setup the new thread 
      clientThread.start(); // start the thread 
     } 

     public void run() 
     { 
      /* this is where you get your input from the console and then 
      * send the output to the client 
      */ 
     } 
    } 
} 

這應該讓你的主線不會卡在server.accept()希望這有助於!

+0

我有點困惑。在'connect(int)'中,客戶端**和**服務器都是這樣嗎?或者僅僅是爲了設置服務器?另外,我沒有看到它有足夠的空間來處理來自控制檯的命令。你能爲我指出一下嗎? – mattbdean

+0

connect(int port)設置服務器,添加一些更多的代碼來澄清 – John