2016-09-21 246 views
0

我一直在嘗試製作多個客戶端聊天應用程序幾天,並且我已閱讀下面的文檔,並在網上找到一些建議,並提出了以下代碼。 https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later具有多個客戶端的Java服務器客戶端

我在想什麼是製作應用程序並啓動服務器,並通過方法 「startServer();」發送消息和 「sendFromServer(Serializable data)」;

~~~~~問題是我開始的startserver()方法的應用中關閉冷凍,所以我知道我做了錯誤的方式。~~~~~~~~

任何人都可以請給我有關如何正確創建一個多客戶端服務器應用程序的提示? (分別是我試圖讓一個窗格拿着兩個聊天的那一刻,用兩個按鈕來調用「startserver的();」和「startClient()」)

public class Server { 
    private ServerSocket server; 
    private Socket socket; 
    private int port; 
    private Consumer<Serializable> consume; 
    private ConnectionThread thread; 
    private List<ConnectionThread> threads = 
      new ArrayList<ConnectionThread>(); 

    public Server(int port, Consumer<Serializable> consume){ 
     this.port= port; 
     this.consume = consume; 

     try { 
      server = new ServerSocket(port); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

    public void startServer() { 
    if(server == null) { 
     System.out.println("no server"); 
    } 
     while(true) { 
     try { 
     socket = server.accept();  
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     ConnectionThread thread =new ConnectionThread(socket); 
     threads.add(thread); 
     thread.start(); 
    } 
} 
    public void sendFromServer(Serializable data) throws IOException { 
     thread.out.writeObject(data); 
    } 

    private class ConnectionThread extends Thread { 
     private Socket socket; 
     private ObjectOutputStream out;  
     private ConnectionThread(Socket socket){ 
      this.socket = socket; 
     } 
     @Override 
     public void run(){ 
     try { 
     ObjectOutputStream out = new  ObjectOutputStream(socket.getOutputStream());   
     ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); 
     this.out = out; 

     while(true){ 
      Serializable data = (Serializable)in.readObject(); 
      consume.accept(data); 
     } 

     }catch (IOException e){ 
      e.printStackTrace(); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

客戶端

public class Client { 

private int port; 
private String ip; 

private Consumer<Serializable> consume; 
private ConnectionThread thread = new ConnectionThread(); 

public Client(int port, String ip, Consumer<Serializable> consume){ 
    this.port = port; 
    this.ip = ip; 
    this.consume = consume; 
} 

public void startClient(){ 
    thread.start(); 
} 

public void sendFromClient(Serializable data) throws IOException{ 
    thread.out.writeObject(data); 
} 

private class ConnectionThread extends Thread{ 
    private Socket socket; 
    private ObjectOutputStream out;  

    @Override 
    public void run(){ 

    try(
      Socket socket = new Socket(ip, port); 
      ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());  
      ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); 
      ) { 
      this.out = out; 

    while(true){ 
     Serializable data = (Serializable)in.readObject(); 
     consume.accept(data); 
      } 
    } catch (Exception e) { 
     e.printStackTrace();; 
    } 
    } 
} 

}

的FXML控制器類

public class chatController{ 
@FXML private TextArea SerBoard, CliBoard; 
@FXML private TextField SerTxt,CliTxt; 
@FXML private Button SerConnect, CliConnect; 
private Server server = createSer(); 
private Client client = createCli(); 
private int port= 5555; 
private String ip = "localhost"; 
private boolean connected = 
     (server==null && client==null)? false: true; 

@FXML 
public void setOnSerConnect(ActionEvent event) { 
    server.startServer(); 
} 
@FXML 
public void setOnCliConnect(ActionEvent event) { 
    client.startClient(); 
} 

private Client createCli() { 
    Client client = new Client(port, ip, data->{ 
     Platform.runLater(() -> { 
      CliBoard.appendText(data.toString()); 
     }); 
    }); 
    System.out.println("Client connect"); 
    return client; 
} 

private Server createSer() { 
    Server server = new Server(port, data->{ 
     Platform.runLater(()->{ 
      SerBoard.appendText(data.toString()); 
     }); 
    }); 
    System.out.println("Server connect"); 
    return server; 
} 

@FXML 
public void setOnSerText(ActionEvent event) { 
    if(connected) { 
    String input = SerTxt.getText(); 
    String mes = "Server: "+ input + "\n"; 
    SerTxt.clear(); 
    SerBoard.appendText(mes); 
      try { 
       server.sendFromServer(mes); 
      } catch (IOException e) { 
       e.printStackTrace(); 
     } 
    } 

} 

@FXML 
public void setOnCliText(ActionEvent event) {  
    if(connected) { 
    String input = SerTxt.getText(); 
    String mes = "Client: "+ input + "\n"; 
    SerTxt.clear(); 
    SerBoard.appendText(mes); 
      try { 
       client.sendFromClient(mes); 
      } catch (IOException e) { 
       e.printStackTrace(); 
     } 
    } 
} 

}

+0

也發佈您的客戶端源代碼。 –

+0

是的,先生,我已經發布了一切...我想知道如果它是startServer();方法是不正確的,因爲窗口被凍結一旦方法被調用 – EricHo

回答

0

應該是相當

public void startServer() { 
if(server == null) { 
    System.out.println("no server"); 
} 
    while(true) { 
    try { 
    socket = server.accept(); 
    ConnectionThread thread =new ConnectionThread(socket); 
    threads.add(thread); 
    thread.start();  
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

} 

這樣你也會acceppt所有客戶端連接。

還必須使用Platform.runLater調用startServer

+0

請問如何使用Platform.runLater調用startServer方法?其實我不太清楚Platform.runLater是如何工作的,對不起 – EricHo

+0

其實我錯了,'startServer'應該從新的單獨線程調用,因爲它會無限地阻塞(有'while(true)'loop)。您在GUI線程內調用它(作爲對某種排序事件的響應,例如,按鈕單擊),導致GUI線程在'while循環中阻塞 - 這就是您的窗口被凍結的原因。 – Antoniossss