2015-11-22 128 views
1

我正嘗試在java中編寫多線程客戶端服務器聊天應用程序。 我只想創建兩個線程,從每個線程發送一些號碼,並從服務器獲取相同的號碼。但有些事情出錯了。 Client sends numbers just from one thread and Server returns not all numbersjava中的多線程客戶端服務器聊天應用程序

下面是客戶端代碼

import java.io.*; 
import java.net.*; 

public class Client implements Runnable{ 

    private Socket clientSocket = null; 
    private DataInputStream input = null; 
    private PrintStream output = null; 
    private DataInputStream inputLine = null; 
    private int id; 

    public Client(int id){ 
     this.id = id; 
    } 

    public static void main(String[] args) throws IOException, InterruptedException { 

     System.out.println("The client started. Type any text. To quit it type 'Ok'."); 

     Client a = new Client(1); 
     Thread one = new Thread(a); 

     Client b = new Client(2); 
     Thread two = new Thread(b); 
     one.start(); 
     two.start(); 

     one.join(); 
     two.join();    

    } 

    public void run() { 
     System.out.println("hi from thread" + id); 
     try { 
      clientSocket = new Socket("localhost", 4444); 
      output = new PrintStream(clientSocket.getOutputStream()); 
      input = new DataInputStream(clientSocket.getInputStream()); 
      inputLine = new DataInputStream(new BufferedInputStream(System.in)); 
     } 
     catch(IOException e){ 
      System.out.println(e); 
     } 
     String responseLine; 
     try{  
      for(int i = 0; i < 10; i++){ 
       output.println(id + " " + i); 
       System.out.println("sended:" + id + " " + i); 
       responseLine = input.readLine(); 
       System.out.println("received: " + responseLine); 
      } 
     } 
     catch (IOException e) { 
      System.out.println(e); 
     } 
    } 

} 

和服務器代碼

import java.io.*; 
import java.net.*; 

public class Server implements Runnable{ 
    private static ServerSocket MyService = null;   
    private DataInputStream input = null; 
    private PrintStream output = null; 
    private String line; 
    private static Socket serviceSocket = null; 

    public static void main(String[] args) throws IOException { 


     try{ 
      MyService = new ServerSocket(4444); 
      if(args.length > 0){ 
       MyService = new ServerSocket(Integer.parseInt(args[0])); 
      } 
     } 
     catch(IOException e){ 
      System.out.println("Couldn't linputten to port " + (args.length > 0 ? Integer.parseInt(args[0]) : 4444)); 
     } 

     System.out.println("The server started. To stop it press <CTRL><C>."); 
     while(true){ 
      try { 
       serviceSocket = MyService.accept();    
       new Thread(new Server()).start(); 
       System.out.println("CREATED"); 
      } 
      catch (IOException e) { 
       System.out.println("can't accept"); 
      } 
     } 

    } 

    public void run(){ 
     try {  
      input = new DataInputStream(serviceSocket.getInputStream()); 
      output = new PrintStream(serviceSocket.getOutputStream()); 
      while (true) { 
       line = input.readLine(); 
       System.out.println("from client:" + line+"\n"); 
       output.println("From server: " + line+"\n"); 

      } 

     } 
     catch(IOException e) { 
      System.out.println(e); 
     } 
    } 

} 
+0

主題。加入服務器缺失 –

回答

1

每一個新的客戶端應該在單獨的Thread在服務器端,要指定一個newSocketserviceSocket並通過你基本上忽略以前連接的客戶端

您開始new Server而不是爲剛剛連接的客戶端啓動Thread。您應該爲連接的每個客戶端創建一個new Socket,並在連接客戶端後在new Thread未啓動new Server上運行它。

UPDATE

下面是一個基本的多個客戶端的服務器的一個示例:

服務器代碼由幾類:

// Server.java 
public class Server { 

    private ServerSocket  socket; 
    private ConnectionListener connectionListener; 

    // temp 
    private List<Client> clientList = new ArrayList<Client>(); 
    // temp end 

    public Server(int port) { 
     try { 
      socket = new ServerSocket(port); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     connectionListener = new ConnectionListener(this); 
    } 

    public void start() throws IOException { 

     connectionListener.start(); 

     // temp will move to a Thread later 
     BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in)); 
     String input; 
     while (((input = stdIn.readLine()) != null) && connectionListener.isAlive()) { 
      if (input.equalsIgnoreCase("exit")) { 
       break; 
      } else { 
       for (int i = 0; i < input.length(); i++) 
        System.out.print("\b"); 
       System.out.println("Admin: " + input); 
       for (Client c : clientList) { 
        c.send("Admin: " + input); 
       } 
      } 

     } 
     stop(); 
     // temp end 
    } 

    public void stop() { 

     connectionListener.stop(); 
     for (Client c : clientList) { 
      c.closeSession(); 
     } 

     System.out.println("Server terminated!"); 
    } 

    public synchronized void addConnection(Connection connection) { 

     Client c = new Client(connection, clientList); 
     clientList.add(c); 
     c.startSession(); 
     System.out.println("Client connected"); 
    } 

    public ServerSocket getSocket() { 

     return socket; 
    } 

    public static void main(String[] args) throws IOException { 

     int port; 
     if (args.length > 0) 
      port = Integer.parseInt(args[0]); 
     else 
      port = 4444; 
     Server s = new Server(port); 
     s.start(); 
    } 

} 

// ConnectionListener.java 
public class ConnectionListener implements Runnable { 

    private Server   server; 
    private ServerSocket socket; 
    private boolean   running; 
    private Thread   t; 

    public ConnectionListener(Server server) { 
     this.server = server; 
     this.socket = server.getSocket(); 
     running = false; 
    } 

    public synchronized void start() { 

     if (running) 
      return; 

     running = true; 
     t = new Thread(this); 
     t.start(); 
    } 

    public synchronized void stop() { 

     if (!running) 
      return; 

     System.out.print("Terminating connection listener on:" + socket.getLocalSocketAddress() + "..."); 

     running = false; 

     try { 
      socket.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     try { 
      t.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

     System.out.println("TERMINATED!"); 
    } 

    @Override 
    public void run() { 

     System.out.println("Listening for connections on: " + socket.getLocalSocketAddress()); 

     try { 
      while (running) { 
       Socket request = socket.accept(); 
       Connection connection = new Connection(request); 
       server.addConnection(connection); 
      } 
     } catch (IOException e) { 
      //e.printStackTrace(); 
     } 

    } 

    public boolean isAlive() { 

     return running; 
    } 

} 

// Connection.java 
public class Connection { 

    private Socket   socket; 
    private BufferedReader in; 
    private BufferedWriter out; 
    private boolean   alive; 

    public Connection(Socket socket) { 
     this.socket = socket; 
     try { 
      in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
      out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     alive = true; 
    } 

    public String read() { 

     try { 
      if (in.ready()) { 
       return in.readLine(); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     return null; 
    } 

    public void write(String data) { 

     try { 
      out.write(data); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void flush() { 

     try { 
      out.flush(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public boolean close() { 

     boolean result = true; 
     try { 
      in.close(); 
      out.close(); 
      socket.close(); 
      alive = false; 
     } catch (IOException e) { 
      e.printStackTrace(); 
      result = false; 
     } 
     return result; 
    } 

    public boolean isAlive() { 

     return alive; 
    } 

} 

// Client.java 

/* 
* This is still server side, that is the handler for the connected clients 
*/ 
public class Client implements Runnable { 

    public static final long IDLE_TIME = 10; 

    private Connection connection; 
    private boolean  alive; 
    private Thread  t; 

    private List<Client> clientList; 

    public Client(Connection connection, List<Client> clientList) { 
     this.connection = connection; 
     this.clientList = clientList; 
     alive = false; 
    } 

    public synchronized void startSession() { 

     if (alive) 
      return; 

     alive = true; 

     t = new Thread(this); 
     t.start(); 

    } 

    public synchronized void closeSession() { 

     if (!alive) 
      return; 

     alive = false; 

     try { 
      connection.close(); 
      t.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void run() { 

     while (connection.isAlive()) { 

      String in = connection.read(); 
      if (in != null) { 
       System.out.println(in); 
       for (Client c : clientList) { 
        c.send(in); 
       } 
      } else { 
       try { 
        Thread.sleep(IDLE_TIME); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 

     } 

    } 

    public void send(String msg) { 

     connection.write(msg + "\n"); 
     connection.flush(); 
    } 

} 

和客戶端例如:

// Client.java 
public class Client { 

    public static void main(String[] args) { 

     String host; 
     if (args.length > 0) 
      host = args[0]; 
     else 
      host = "localhost"; 

     int port; 
     if (args.length > 1) 
      port = Integer.parseInt(args[1]); 
     else 
      port = 4444; 

     try (Socket socket = new Socket(host, port); 
       BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
       BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 
       BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { 

      Thread input = new Thread(() -> { 
       String msg; 
       try { 
        while ((msg = in.readLine()) != null) { 
         System.out.println(msg); 
        } 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      }); 
      input.start(); 

      String userName = "User" + ((int) (Math.random() * 200)); 
      String msg; 
      try { 
       while ((msg = stdIn.readLine()) != null) { 
        for (int i = 0; i < msg.length(); i++) 
         System.out.print("\b"); 
        out.write(userName + ": " + msg + "\n"); 
        out.flush(); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

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

    } 

} 

這不是最好的例子,但我希望你可以使用它,並調整您的需求。

+0

所以,我需要在這裏創建新的套接字? while(true){ 嘗試serviceSocket = MyService.accept(); ... 以及如何創建新的線程,而不是啓動新的服務器? –

+0

創建某種線程化的客戶端處理程序。在新線程上運行新的處理程序,以便爲每個連接的客戶機運行一個線程。 –

+0

我瞭解你,謝謝。 –

相關問題