2013-10-13 175 views
1

我試圖製作一個簡單的可以管理更多客戶端的ECHO服務器。多線程服務器Java

服務器類:

public class EchoServer { 

    protected int   port ; 
    protected ServerSocket socket; 
    private Socket  acceptedSocket; 

    public EchoServer(int port) throws IOException { 
     this.port = port; 
     socket = new ServerSocket(port); 
    } 

    public void start() throws AcceptingClientException { 
     while(!socket.isClosed()) { 
     try { 
      acceptedSocket = socket.accept(); 
     } 
     catch (IOException e){ 
      throw new AcceptingClientException(); 
     } 
     ClientHandler ch = new ClientHandler(acceptedSocket); 
     ch.run(); 
     } 
    } 
} 

Runnable接口的客戶端處理程序:

public class ClientHandler implements Runnable { 

    Socket socket; 

    public ClientHandler(Socket socket) { 
     this.socket = socket; 
    } 

    @Override 
    public void run() { 
     PrintWriter From_Server = null; 
     BufferedReader To_Server = null; 
     String to_server_string = null; 
     try { 
     From_Server = new PrintWriter(socket.getOutputStream()); 
     To_Server = 
      new BufferedReader(
       new InputStreamReader(socket.getInputStream())); 
     System.out.println("Stream opened.\n"); 
     while(true) { 
      if(To_Server.ready()){ 
       System.out.println("Reading input line.\n"); 
       to_server_string = To_Server.readLine(); 
       if(to_server_string.equalsIgnoreCase("quit")) { 
        System.out.println("Connection closed on user request.\n"); 
        From_Server.print("Bye :)\n"); 
        From_Server.close(); 
        To_Server.close(); 
        socket.close();    
       } 
       else { 
        System.out.println(
        "String '" + 
        to_server_string+"' is not 'quit', echoing.\n"); 
        From_Server.print("ECHO: "+to_server_string+"\n"); 
        System.out.println("String written on stream, flushing.\n"); 
        From_Server.flush(); 
       } 
      } 
     } 
     } 
     catch (IOException e) { 
     System.out.println("Stream error (connection closed?).\n"); 
     } 
    } 
} 

主類

public static void main(String[] args) { 
    try { 
     EchoServer server= new EchoServer(9999); 
     server.start(); 
    } 
    catch (IOException ex) { 
     System.out.println("Unable to start server (port is busy?)\n"); 
     Logger.getLogger(SimpleServer.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    catch (AcceptingClientException e){ 
     System.out.println("Unable to accept client\n"); 
    } 
} 

多個客戶端能夠連接到服務器,但ECHO會當時只與一個客戶端一起工作(如果我關閉與一個客戶端的連接,服務器將開始處理另一個自動),但我不明白爲什麼:當一個客戶端連接到服務器時,與server.accept()創建相關聯的socked被傳遞給一個可運行的客戶端處理程序的新實例,該處理程序以handler.run ),並且服務器應該返回server.accept()中等待(除非ServerSocket已關閉)。 我假設的問題,應該是與服務器類的這個方法:

public void start() throws AcceptingClientException { 
    while(!socket.isClosed()) { 
     try { 
     acceptedSocket=socket.accept(); 
     } 
     catch (IOException e){ 
     throw new AcceptingClientException(); 
     } 
     ClientHandler ch = new ClientHandler(acceptedSocket); 
     ch.run(); 
    } 
} 

但我無法弄清楚什麼是錯的......我缺少什麼?

+0

代碼太多,發佈了[SSCCE](http://sscce.org/)。 –

+0

錯誤是在第21行和第22行,我沒有看到其餘的代碼... – Aubin

+0

ready()測試實際上是一個完全浪費時間。如果刪除它,代碼將繼續像現在一樣運行,但CPU將停止吸菸。 – EJP

回答

1

您的代碼:

ClientHandler ch = new ClientHandler(acceptedSocket); 
ch.run(); 

並不在同一個線程啓動一個新線程,它委託給ClientHandler.run()

要啓動線程,請使用new Thread(ch).start();,因爲ch屬於類ClientHandler,它實現Runnable

+0

非常感謝,我甚至不知道我是如何錯過的,現在它的工作原理! – Flashgun

+0

@Flashgun您是否知道當您點擊答案旁邊的綠色複選標記時,它將答案標記爲「已接受」?這清楚表明它的工作。有關此主題的更多信息,請參閱[幫助中心](http://stackoverflow.com/help/accepted-answer)。 – tbodt

+0

@tbodt:我相信,新用戶無法立即接受答案。 – Aubin