2012-06-03 3 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

Я думаю, что ваш командный процессор должен находиться в другом потоке. IMHO сервер должен всегда иметь поток, который должен выполнять только новое соединение и отправлять его. Обработка вашего входа должна быть частью другого потока.

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

Смежные вопросы