2012-10-29 21 views
15

Tak więc teraz robię wielowątkowy oparty na aplikacji klienckiej. Po stronie serwera tworzę wątek dla każdego zaakceptowanego połączenia.Wysyłanie wiadomości do wszystkich klientów (klient - komunikacja z serwerem)

W klasie wątków wykonuję metodę, która wysyła polecenie do klienta. Czego chcę tylko, to, jak wysłać parametr do wszystkich działających klientów? Dla prostych instrukcji, chcę tylko sprawić, aby serwer wysyłał wiadomości do wszystkich podłączonych klientów.

Przeczytałem this post i odnaleziono metodę sendToAll(String message) od . Ale kiedy próbuję w moim kodzie, nie ma takiej metody w ServerSocket.

OK, to jest mój przykładowy kod dla serwera i wątku.

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) {} 
} 

} 

Dzięki za pomoc :)

Odpowiedz

19

Poniższa odpowiedź, nie jest zalecany do pełnego serwera rozwiniętego, a do tego należy korzystać z apletów Java EE, usług internetowych itp

ten przeznaczony jest tylko kilka komputerów, gdzie chcą połączyć się, aby wykonać określone zadanie, a używanie prostych gniazd Java nie stanowi ogólnego problemu. Pomyśl o komputerach rozproszonych lub grach wieloosobowych.

EDIT: ja - od pierwszego postu - znacznie aktualizowane tę architekturę, teraz przetestowany i bezpieczny wątku. Każdy, kto tego potrzebuje, może pobrać go pod numer here.

Po prostu użyj (bezpośrednio lub przez podklasę) Server i Client, start(), i wszystko jest gotowe. Przeczytaj komentarze wbudowane, aby uzyskać bardziej zaawansowane opcje.


Podczas gdy komunikacja między klientami jest dość skomplikowana, postaram się ją uprościć, jak to tylko możliwe.

Oto punkty, w serwerze:

  • Utrzymanie listę podłączonych klientów.
  • Definiowanie wątku dla wejścia serwera.
  • Definiowanie kolejki odebranych wiadomości.
  • Odpytywanie w wątku z kolejki i praca z nim.
  • Niektóre metody użytkowe do wysyłania wiadomości.

I dla klienta:

  • Definiowanie wątku, dla wejścia klienta.
  • Definiowanie kolejki odebranych wiadomości.
  • Odpytywanie w wątku z kolejki i praca z nim.

Oto klasa serwera:

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); 
    } 

} 

I tu dla klasy Client:

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

Twoja odpowiedź brzmi świetnie, ale brakuje Ci kilku dwukropek i należy zmienić 'messages.dequeue();' i 'messages.enqueue();' na 'messages.take();' i ' messages.put(); ' – Danon

+1

Czy jesteś pewien, że ta klasa jest bezpieczna dla wątków? Mam na myśli, co jeśli wzywam sendToOne()/sendToAll w czasie akceptować/wątki zmiany clientList? – Danon

+0

@Danon Zobacz edycję. – Mordechai

3

nie ma metody w gnieździe serwera, aby wysłać dane lub wiadomość do wszystkich uruchomionych wątków clinet. Proszę przejść przez program ServerThread.java, który wywołuje serwer usng sendToAll.

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

Wyjazd zeroMQ. Istnieją metody znane jako "pub sub" lub "publish subscribe", które wykonają to, co chcesz. Możesz również użyć go do komunikacji między wątkami. Zdumiewająca biblioteka jest moim zdaniem. Posiada powiązania java lub jzmq wraz z ponad 30 innymi, więc powinieneś być w stanie używać go w swoim programie.

http://www.zeromq.org/

Powiązane problemy