2012-08-13 208 views
0

基本上我想要做的是開發一個聊天程序(即時通訊和IRC之間的東西),以提高我的Java技能。處理多客戶端流?

但到目前爲止我遇到了一個大問題:如果有多個客戶端,我不知道如何正確設置流。客戶端和服務器之間的1:1聊天工作很容易,但我只是不知道該怎麼辦,所以在同一個聊天中可以有多於一個客戶端與服務器通信。

這就是我得到的結果,但我懷疑它會非常有幫助,因爲它只是1個永久流向和來自服務器。

private void connect() throws IOException { 
     showMessage("Trying to connect \n"); 
     connection = new Socket(InetAddress.getByName(serverIP),27499); 
     showMessage("connected to "+connection.getInetAddress().getHostName()); 

    } 

    private void streams() throws IOException{ 
     output = new ObjectOutputStream(connection.getOutputStream()); 
     output.flush(); 
     input = new ObjectInputStream(connection.getInputStream()); 
     showMessage("\n streams working"); 

    } 

回答

0

要從一個程序中的多個流讀取,您將不得不使用多線程。因爲從流中讀取是同步的,所以您需要從每個線程的一個流中讀取數據。有關多線程的更多信息,請參閱java tutorial on threads

0

幾個月前做出這樣的事情。基本上我在每個客戶端服務器端使用單獨的ServerSocketThread。當客戶端連接時,您將該端口的輸入和輸出流注冊到固定池並阻塞,直到發送輸入。然後將輸入複製到其他每個客戶端併發送。這裏是從命令行運行的基本程序: Server代碼:

import java.io.*; 
    import java.net.ServerSocket; 
    import java.net.Socket; 
    import java.util.ArrayList; 

    public class ChatServer { 

     static int PORT_NUMBER = 2012; 

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


      while (true) { 
       try (ServerSocket ss = new ServerSocket(PORT_NUMBER)) { 
        System.out.println("Server waiting @" + ss.getInetAddress()); 
        Socket s = ss.accept(); 
        System.out.println("connection from:" + s.getInetAddress()); 

        new Worker(s).start(); 
       } 
      } 

     } 

     static class Worker extends Thread { 

      final static ArrayList<PrintStream> os = new ArrayList(10); 
      Socket clientSocket; 
      BufferedReader fromClient; 

      public Worker(Socket clientSocket) throws IOException { 
       this.clientSocket = clientSocket; 
       PrintStream toClient=new PrintStream(new BufferedOutputStream(this.clientSocket.getOutputStream())); 
       toClient.println("connected to server"); 
       os.add(toClient); 
       fromClient = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream())); 

      } 
      @Override 
      public void run() { 

       while (true) { 
        try { 
         String message = fromClient.readLine(); 
         synchronized (os) { 


          for (PrintStream toClient : os) { 
           toClient.println(message); 
           toClient.flush(); 
          } 
         } 

        } catch (IOException ex) { 
         //user discnnected 
         try { 
          clientSocket.close(); 
         } catch (IOException ex1) { 

         } 
        } 

       } 
      } 
     } 

} 

客戶端代碼:

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintStream; 
import java.net.Socket; 

public class Client { 

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

     final BufferedReader fromUser = new BufferedReader(new InputStreamReader(System.in)); 
     PrintStream toUser = System.out; 
     BufferedReader fromServer; 
     final PrintStream toServer; 
     Socket s = null; 

     System.out.println("Server IP Address?"); 


     String host; 
     String port = ""; 


     host = fromUser.readLine(); 

     System.out.println("Server Port Number?"); 

     port = fromUser.readLine(); 

     s = new Socket(host, Integer.valueOf(port)); 

     int read; 
     char[] buffer = new char[1024]; 


     fromServer = new BufferedReader(new InputStreamReader(s.getInputStream())); 
     toServer = new PrintStream(s.getOutputStream()); 
     new Thread() { 

      @Override 
      public void run() { 
       while (true) { 
        try { 
         toServer.println(">>>" + fromUser.readLine()); 

         toServer.flush(); 
        } catch (IOException ex) { 
         System.err.println(ex); 
        } 
       } 
      } 
     }.start(); 
     while (true) { 
      while ((read = fromServer.read(buffer)) != -1) { 
       toUser.print(String.valueOf(buffer, 0, read)); 
      } 
      toUser.flush(); 

     } 
    } 
} 
0

我已經ServerSocket(int port)Socket ServerSocket.accept()這樣做幾次。這可以通過讓它監聽您希望聊天服務器客戶端偵聽的一個端口來實現。主線程將阻塞等待下一個客戶端連接,然後將Socket對象返回給該特定客戶端。通常你會想把它們放在一個列表中來統一處理n個客戶端。

而且,是的,您可能想要確保每個Socket處於不同的線程中,但這完全取決於您作爲程序員。記住,由於客戶端使用不同的源端口,所以不需要重定向到服務器上的另一個端口,唯一的5元組(SrcIP,SrcPort,DstIP,DstPort,TCP/UDP /其他IP協議)將允許一個服務器端口被重新使用。因此,爲什麼我們都使用stackoverflow.com的端口80.

快樂編碼。