2012-10-29 56 views
15

Vì vậy, bây giờ, tôi đang tạo một ứng dụng khách đa nhiệm dựa trên ứng dụng máy khách. Ở phía máy chủ, tôi tạo một luồng cho kết nối mọi thứ được chấp nhận.Gửi tin nhắn đến tất cả khách hàng (Client - Server communication)

Trong lớp chuỗi, tôi tạo một phương thức gửi lệnh cho khách hàng. Những gì tôi chỉ muốn là, làm thế nào để gửi một tham số cho tất cả các khách hàng đang chạy? Đối với tuyên bố đơn giản, tôi chỉ muốn làm cho máy chủ này gửi một tin nhắn đến tất cả các khách hàng kết nối.

Tôi đã đọc this post và tìm phương thức sendToAll(String message) từ this link. Nhưng khi tôi cố gắng trong mã của tôi, không có phương pháp như thế trong ServerSocket.

OK đây là mã mẫu của tôi cho máy chủ và chuỗi.

class ServerOne{ 

ServerSocket server = null; 
... 

ServerOne(int port){ 
      System.out.println("Starting server on port "+port); 
    try{ 
     server = new ServerSocket(port); 
       System.out.println("Server started successfully and now waiting for client"); 

    } catch (IOException e) { 
     System.out.println("Could not listen on port "+port); 
     System.exit(-1); 
    } 
} 

public void listenSocket(){ 
    while(true){ 
     ClientWorker w; 
     try{ 
      w = new ClientWorker(server.accept()); 
      Thread t = new Thread(w); 
      t.start(); 
     } catch (IOException e) { 
      System.out.println("Accept failed: 4444"); 
      System.exit(-1); 
     } 
    } 
} 

protected void finalize(){ 
    try{ 
     server.close(); 
    } catch (IOException e) { 
     System.out.println("Could not close socket"); 
     System.exit(-1); 
    } 
} 
} 

class ClientWorker implements Runnable{ 
Socket client; 

ClientWorker(Socket client){ 
    this.client = client; 
} 
public void run(){ 
    ... 
     sendCommand(parameter); 
    ... 
} 

public void sendCommand(String command){ 
    PrintWriter out = null; 
    try { 
     out = new PrintWriter(client.getOutputStream(), true); 
     out.println(command); 
    } catch (IOException ex) {} 
} 

} 

Nhờ sự giúp đỡ :)

Trả lời

19

Câu trả lời dưới đây, không được khuyến khích cho một máy chủ chính thức đầy đủ, như đối với điều này, bạn nên sử dụng Java EE với servlets, dịch vụ web vv

này chỉ được thiết kế nơi một vài máy tính muốn để kết nối để thực hiện một tác vụ cụ thể và việc sử dụng các ổ cắm Java đơn giản không phải là vấn đề chung. Hãy suy nghĩ về tính toán phân tán hoặc chơi trò chơi nhiều người chơi.

CHỈNH SỬA: Tôi - kể từ lần đăng đầu tiên - cập nhật rất nhiều kiến ​​trúc này, hiện đã được kiểm tra và đảm bảo an toàn. Bất kỳ ai cần nó đều có thể tải xuống here.

Chỉ cần sử dụng (trực tiếp hoặc theo phân lớp) ServerClient, start() chúng và mọi thứ đã sẵn sàng. Đọc các bình luận nội tuyến để có các tùy chọn mạnh mẽ hơn.


Trong khi giao tiếp giữa khách hàng khá phức tạp, tôi sẽ cố gắng đơn giản hóa nó, nhiều nhất có thể.

Dưới đây là các điểm, trong máy chủ:

  • Giữ một danh sách khách hàng được kết nối.
  • Xác định chuỗi, cho đầu vào máy chủ.
  • Xác định hàng đợi của các thư đã nhận.
  • Bỏ phiếu chuỗi từ hàng đợi và làm việc với nó.
  • Một số phương pháp tiện ích để gửi tin nhắn.

Và đối với khách hàng:

  • Xác định một chủ đề, cho đầu vào của khách hàng.
  • Xác định hàng đợi của các thư đã nhận.
  • Bỏ phiếu chuỗi từ hàng đợi và làm việc với nó.

Đây là lớp Server:

public class Server { 
    private ArrayList<ConnectionToClient> clientList; 
    private LinkedBlockingQueue<Object> messages; 
    private ServerSocket serverSocket; 

    public Server(int port) { 
     clientList = new ArrayList<ConnectionToClient>(); 
     messages = new LinkedBlockingQueue<Object>(); 
     serverSocket = new ServerSocket(port); 

     Thread accept = new Thread() { 
      public void run(){ 
       while(true){ 
        try{ 
         Socket s = serverSocket.accept(); 
         clientList.add(new ConnectionToClient(s)); 
        } 
        catch(IOException e){ e.printStackTrace(); } 
       } 
      } 
     }; 

     accept.setDaemon(true); 
     accept.start(); 

     Thread messageHandling = new Thread() { 
      public void run(){ 
       while(true){ 
        try{ 
         Object message = messages.take(); 
         // Do some handling here... 
         System.out.println("Message Received: " + message); 
        } 
        catch(InterruptedException e){ } 
       } 
      } 
     }; 

     messageHandling.setDaemon(true); 
     messageHandling.start(); 
    } 

    private class ConnectionToClient { 
     ObjectInputStream in; 
     ObjectOutputStream out; 
     Socket socket; 

     ConnectionToClient(Socket socket) throws IOException { 
      this.socket = socket; 
      in = new ObjectInputStream(socket.getInputStream()); 
      out = new ObjectOutputStream(socket.getOutputStream()); 

      Thread read = new Thread(){ 
       public void run(){ 
        while(true){ 
         try{ 
          Object obj = in.readObject(); 
          messages.put(obj); 
         } 
         catch(IOException e){ e.printStackTrace(); } 
        } 
       } 
      }; 

      read.setDaemon(true); // terminate when main ends 
      read.start(); 
     } 

     public void write(Object obj) { 
      try{ 
       out.writeObject(obj); 
      } 
      catch(IOException e){ e.printStackTrace(); } 
     } 
    } 

    public void sendToOne(int index, Object message)throws IndexOutOfBoundsException { 
     clientList.get(index).write(message); 
    } 

    public void sendToAll(Object message){ 
     for(ConnectionToClient client : clientList) 
      client.write(message); 
    } 

} 

Và đây cho lớp Chủ đầu tư:

public class Client { 
    private ConnectionToServer server; 
    private LinkedBlockingQueue<Object> messages; 
    private Socket socket; 

    public Client(String IPAddress, int port) throws IOException{ 
     socket = new Socket(IPAddress, port); 
     messages = new LinkedBlokingQueue<Object>(); 
     server = new ConnecionToServer(socket); 

     Thread messageHandling = new Thread() { 
      public void run(){ 
       while(true){ 
        try{ 
         Object message = messages.take(); 
         // Do some handling here... 
         System.out.println("Message Received: " + message); 
        } 
        catch(InterruptedException e){ } 
       } 
      } 
     }; 

     messageHandling.setDaemon(true); 
     messageHandling.start(); 
    } 

    private class ConnectionToServer { 
     ObjectInputStream in; 
     ObjectOutputStream out; 
     Socket socket; 

     ConnectionToServer(Socket socket) throws IOException { 
      this.socket = socket; 
      in = new ObjectInputStream(socket.getInputStream()); 
      out = new ObjectOutputStream(socket.getOutputStream()); 

      Thread read = new Thread(){ 
       public void run(){ 
        while(true){ 
         try{ 
          Object obj = in.readObject(); 
          messages.put(obj); 
         } 
         catch(IOException e){ e.printStackTrace(); } 
        } 
       } 
      }; 

      read.setDaemon(true); 
      read.start(); 
     } 

     private void write(Object obj) { 
      try{ 
       out.writeObject(obj); 
      } 
      catch(IOException e){ e.printStackTrace(); } 
     } 


    } 

    public void send(Object obj) { 
     server.write(obj); 
    } 
} 
+0

câu trả lời của bạn là tuyệt vời, nhưng bạn thiếu vài dấu hai chấm và bạn nên thay đổi 'messages.dequeue(); 'và' messages.enqueue(); 'cho' messages.take(); 'và' messages.put(); ' – Danon

+1

Ngoài ra, bạn có chắc lớp này là an toàn không? Tôi có nghĩa là, những gì nếu tôi gọi sendToOne()/sendToAll tại thời điểm chấp nhận/chủ đề thay đổi clientList? – Danon

+0

@Danon Vui lòng xem chỉnh sửa. – Mordechai

3

Không có phương pháp trong ổ cắm máy chủ để gửi dữ liệu hoặc thông điệp tới tất cả các chủ đề clinet chạy. Vui lòng xem qua chương trình ServerThread.java đang gọi máy chủ us2 sendToAll.

// ... and have the server send it to all clients 
server.sendToAll(message); 
2

Check-out zeroMQ. Có những phương thức được gọi là "pub sub" hoặc "publish subscription" sẽ làm những gì bạn muốn. Bạn cũng có thể sử dụng nó để giao tiếp giữa các chủ đề của bạn. Đó là một thư viện tuyệt vời theo ý kiến ​​của tôi. Nó có các liên kết java hoặc jzmq cùng với hơn 30+ người khác nữa nên bạn sẽ có thể sử dụng nó trong chương trình của bạn.

http://www.zeromq.org/

Các vấn đề liên quan