2017-04-12 113 views
0

試圖構建一個簡單的多線程聊天服務器,通過命令提示符運行。客戶端連接到服務器,服務器將保存多個客戶端,但是當試圖從一個客戶端發送消息到另一個客戶端,或者甚至通知另一個用戶登錄的客戶端時,客戶端命令提示符上都不會顯示任何內容。多線程服務器聊天Java - 連接但沒有消息

public class Server { 
private static ServerSocket servSock; 
private static Socket clientSock; 
private static ArrayList<ClientThread> clientList; 
private static int IDcount = 0; 


public static void main(String args[]){ 
     // Get command line arguments. 
     if (args.length != 3) { 
     System.out.println("Required arguments: server port, block duration, timeout"); 
     return; 
     } 
     int port = Integer.parseInt(args[0]); 
     int blockDur = Integer.parseInt(args[1]); 
     int timeout = Integer.parseInt(args[2]); 

     try{ 
     servSock = new ServerSocket(port); 
     clientList = new ArrayList<ClientThread>(); 
     } 
     catch(IOException ex){ 
      System.err.println(ex); 
     } 


     while (true) { 
     try { 
      clientSock = servSock.accept(); 
      ClientThread thread = new ClientThread(clientSock); 
      clientList.add(thread); 
      thread.start(); 
     } catch (IOException e) { 
      System.out.println(e); 
     } 
     } 
    } 

private synchronized static void broadcast(String msg){ 
    System.out.print(msg); 
    for(int i = 0; i < clientList.size(); i++){ 
     ClientThread client = clientList.get(i); 
     client.send(msg); 
    } 

} 

synchronized static void unlist(int id){ 
for(int i = 0; i < clientList.size(); i++){ 
    ClientThread thread = clientList.get(i); 
    if(thread.id == id){ 
     clientList.remove(i); 
     return; 
     } 
    } 
} 

static class ClientThread extends Thread { 
    Socket sock; 
    BufferedReader tIn; 
    PrintWriter tOut; 

    int id; 
    String username; 
    String msg; 

    ClientThread(Socket sock){ 
     id = IDcount++; 
     this.sock = sock; 
     try{ 
      tIn = new BufferedReader(new InputStreamReader(sock.getInputStream())); 
      tOut = new PrintWriter(sock.getOutputStream()); 
      username = tIn.readLine(); 
      broadcast(username + " logged in"); 
     } 
     catch(IOException ex){ 
      System.err.println(ex); 
     } 
    } 

    public void run(){ 
     boolean loggedIn = true; 
     while(loggedIn){ 
      try{ 
       msg = tIn.readLine(); 
      } 
      catch (IOException ex){ 
       System.err.println(ex); 
      } 
      String[] parts = msg.split("\\s",2); 
      String type = parts[0]; 

客戶端代碼類似於

public class Client{ 
private static Socket clientSock; 
private static BufferedReader in; 
private static PrintWriter out; 
private static Scanner scan; 

public static void main(String[] args) throws IOException { 
     if (args.length != 2) { 
      System.out.println("Required arguments: server IP, server port"); 
      return; 
      } 
     String host = args[0]; 
     int port = Integer.parseInt(args[1]); 

     clientSock = new Socket(host, port); 
     in = new BufferedReader(new InputStreamReader(clientSock.getInputStream())); 
     out = new PrintWriter(clientSock.getOutputStream()); 
     scan = new Scanner(System.in); 

     new ListenFromServer().start(); 
     boolean online = true; 

     System.out.println("Enter your username:"); 
     String username = scan.nextLine(); 

     out.println(username); 

     while(online){ 
      System.out.println("> "); 
      String msg = scan.nextLine(); 
      String[] parts = msg.split("\\s"); 
      String type = parts[0]; 
      send(msg); 
      if(type.equalsIgnoreCase("logout")){ 
       online = false; 
      } 


     } 
     logoff(); 
} 

     static void send(String msg) throws IOException{ 
      out.println(msg); 
     } 

     private static void logoff() throws IOException{ 
       in.close(); 
       out.close(); 
       scan.close(); 
       clientSock.close(); 
     } 

    static class ListenFromServer extends Thread{ 
     public void run(){ 
      while(true){ 
       try{ 
        String msg = in.readLine(); 
        System.out.println(msg); 
       } 
       catch(IOException ex){ 
        System.err.println(ex); 
       } 
      } 
     } 
    } 

    } 
+0

您是否試過單步執行代碼?此外,你不想要的地方出現錯誤。 –

回答

0

當你PrintWriter.println(),數據寫入緩衝發送數據。您必須在println之後立即撥打PrintWriter.flush()以立即向服務器發送數據或從服務器發送數據。

而當您在ClientThread構造函數中調用username = tIn.readLine();時,會阻塞主線程,因爲構造函數在main-thread中調用。所以,雖然連接的用戶不會發送用戶名,但其他客戶端無法連接。