title: RMI chat program in java - how to send mesage from client to client (not through the server)?
body: <p>I cannot get the client to send a message to another client without going through the server. It is an obligatory school project that should be implemented like that. I would appreciate it if someone could help me.</p>
  
  <p><em>Server Interface:</em>
  </p>
  
  <pre class="lang-java prettyprint-override"><code>import java.rmi.Remote;
  import java.rmi.RemoteException;
  import java.util.ArrayList;
  import java.util.List;
  
  public interface ChatServerInt extends Remote {
      public abstract void register(ChatClientInt inClient) throws RemoteException;
      public abstract ChatClientInt[] getClients() throws RemoteException;
      public void disconnect(ChatClientInt client) throws RemoteException;
  } 
  </code></pre>
  
  <p><em>Server Implementation:</em> </p>
  
  <pre class="lang-java prettyprint-override"><code>import java.rmi.Naming;
  import java.rmi.RemoteException;
  import java.rmi.server.UnicastRemoteObject;
  import java.util.ArrayList;
  import java.util.List;
  import java.util.Random;
  
  public class ChatServerImp extends UnicastRemoteObject implements ChatServerInt, Runnable {
      private ChatClientInt[] clientList;
      int counter = 0;
      private ArrayList&lt;String&gt; connectedClients; 
      /**
       * List of all registered remote clients. 
       */
      private List&lt;ChatClientInt&gt; clients = null; 
  
      /**
       * Construct an instance of the chat server. 
       */
      public ChatServerImp() throws RemoteException {
          // initialise the list of client objects.
          clients = new ArrayList&lt;ChatClientInt&gt;();
          connectedClients = new ArrayList&lt;String&gt;();
          clientList = new ChatClientInt[16];
      }
  
      /**
       * Register a chat client. 
       */
      public void register(ChatClientInt inClient) throws RemoteException {
          // perform registration. 
          synchronized(clients)
          {
              clients.add(inClient);
              clientList[counter++] =  inClient;
              inClient = new ChatClientImp();
  
              for(int i = 0 ; i &lt; clients.size();i++) {
                  System.out.println(inClient.getName()+ "has joined\n");
              }
          }
      }
  
      /**After registering, each client will request the list of connected users. 
       * Get a list of chat clients. 
       */
      public synchronized ChatClientInt[] getClients() throws RemoteException {
          // generate and return the list
          return clientList;
      }
  
      public void disconnect(ChatClientInt client) throws RemoteException {
          for(int i = 0; i &lt; clients.size(); i++) {
              System.out.println(client.getName() + "" + "has joined \n");
          }
          clients.remove(client);
      }
  
      /**
       * Generate a random subset. Based on an implementation of D. Knuth's 
       * @return
       */
      private static &lt;T&gt; List&lt;T&gt; randomSample2(List&lt;T&gt; items, int m) {
          Random rnd = new Random();
          for(int i=0;i&lt;items.size();i++){
              int pos = i + rnd.nextInt(items.size() - i);
              T tmp = items.get(pos);
              items.set(pos, items.get(i));
              items.set(i, tmp);
          }
          return items.subList(0, m);
      }   
  
      /**
       * Run the server's main thread. The server should periodically 
       * iterate through all registered clients to find out if they 
       * are still alive. Any dead clients will be removed from the 
       * client list. 
       */
  
      public void run() {
          while(true) {
              //System.out.println("waiting for client connection....\n");
              // sleep for a while
              try {
                  Thread.sleep(5000);
                  // iterate through all the clients we know. if we can't communicate with the client
                  // then eliminate it else if we can communicate with the client then do nothing. 
                  for(int i =0; i &lt; clients.size(); i++) {
                      try {
                          if(clients.get(i).getName()==null) {
                              clients.remove(clients.get(i).getName());
                              System.out.println("Disconnected clients:\n" + clients.get(i).getName());
                          }
                      }
                      catch (RemoteException e) {e.printStackTrace();}
                  }           
              } 
              catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
      }
  
      /**
       * Start the chat server. 
       * @param args
       */
      public static void main(String[] args) throws Exception {
          //ChatServerInt server;
          try {
              String serverName = "rmi://localhost/ChatServer";
              // create an instance of the chat server
              //server = (ChatServerImp) new ChatServerImp();
  
              //Launch the registry - saves invoking it manually
              java.rmi.registry.LocateRegistry.createRegistry(1099);
  
              // register the instance with the RMIRegistry
              Naming.rebind(serverName, new ChatServerImp());
  
              //Naming.rebind(serverName, server);
  
              // create the server thread and start it
              //Thread t = new Thread(server).start();
  
              System.out.println("Server running.....\n");
          }
          catch(RemoteException ex) {
              System.out.println("Error binding the server to rmi");
          }
      }
  }
  </code></pre>
  
  <p><em>Message Interface:</em></p>
  
  <pre class="lang-java prettyprint-override"><code>import java.util.HashSet;
  
  public interface MessageInt {
      /**
       * Add a chat recipient to the list of receivers
       * @param inClient
       */
      public abstract void addRecipient(ChatClientInt inClient);
  
      /**
       * Get the set of clients that have seen this message
       * @return
       */
      public abstract HashSet&lt;ChatClientInt&gt; getRecipients();
  
      /**
       * Get the message content.  
       * @return
       */
      public abstract String getContent();
  
      /**
       * Get an ID for a sender of the message
       * @return
       */
      public abstract String getSource();
  
  }
  </code></pre>
  
  <p><em>Message Implementation:</em></p>
  
  <pre class="lang-java prettyprint-override"><code>import java.io.Serializable;
  import java.util.HashSet;
  
  public class MessageImp implements MessageInt, Serializable {
      /**
       * 
       */
      private static final long serialVersionUID = -2686034785384409672L;
      HashSet&lt;ChatClientInt&gt; clientSet = new HashSet&lt;ChatClientInt&gt;();
  
      String messageContent;
      String messageSource;
  
      public MessageImp(String inUser , String inMsg) {
          messageSource = inUser;
          messageContent = inMsg;
      }
  
      /**
       * Add a chat recipient to the list of receivers
       * @param inClient
       */
      public void addRecipient(ChatClientInt inClient) {
          synchronized(inClient) {
              clientSet.add(inClient);
          }
      }
  
      /**
       * Get the set of clients that have seen this message
       * @return
       */
      public HashSet&lt;ChatClientInt&gt; getRecipients() {
          return clientSet;   
      }
  
      /**
       * Get the message content.  
       * @return
       */
      public String getContent() {
          return messageContent;  
      }
  
      /**
       * Get an ID for a sender of the message
       * @return
       */
      public String getSource() {
          return messageSource;   
      }
  }
  </code></pre>
  
  <p><em>Client Interface:</em></p>
  
  <pre class="lang-java prettyprint-override"><code>import java.rmi.Remote;
  import java.rmi.RemoteException;
  
  public interface ChatClientInt extends Remote {
      /**
       * Process a newly received message. 
       * 
       * @param inMessage
       */
      public void processMessage(MessageInt inMessage)throws RemoteException; 
  
      /**
       * Returns the name of the client. 
       */
      public String getName() throws RemoteException; 
  
      public boolean sendMessage(MessageInt inMessage) throws RemoteException;
  
  }
  </code></pre>
  
  <p><em>Client Implementation:</em></p>
  
  <pre class="lang-java prettyprint-override"><code>import java.io.Serializable;
  import java.net.MalformedURLException;
  import java.rmi.Naming;
  import java.rmi.NotBoundException;
  import java.rmi.RemoteException;
  import java.rmi.server.UnicastRemoteObject;
  import java.util.ArrayList;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Scanner;
  
  public class ChatClientImp extends UnicastRemoteObject implements ChatClientInt, Runnable {
      /**
       * 
       */
      private static final long serialVersionUID = 74130345076834009L;
  
      private ArrayList &lt;String&gt; eventHistory = new ArrayList&lt;String&gt;();
  
      private HashSet&lt;ChatClientInt&gt; clientSet = new HashSet&lt;ChatClientInt&gt;();
  
      private List&lt;ChatClientInt&gt; clients;// = new ArrayList&lt;ChatClientInt&gt;();
  
      ChatClientInt[] listFromServer = new ChatClientInt[4];
  
      String clientName;
      String strMessage;
      MessageInt messageObj;
      ChatServerInt serverObj;
  
  
      public ChatClientImp() throws RemoteException {
          super();    
          clients = new ArrayList&lt;ChatClientInt&gt;();   
      }
  
      public void processMessage(MessageInt inMessage) throws RemoteException {   
          System.out.println("message:" + inMessage.getRecipients().toString() + inMessage.getSource() + inMessage.getContent() + "\n");      
      }
  
  
      public String getName() throws RemoteException {
          return clientName;
      }
  
      public synchronized boolean sendMessage(MessageInt inMessage) throws RemoteException {
          boolean success = false;    
          for(int i = 0; i &lt; clients.size(); i++) {
              clients.get(i).processMessage(inMessage);
              inMessage.addRecipient(clients.get(i));
              success = true;
          }
          return success;
      }
  
      public void displayMessage(String displayName, String displayMsg) {
          Iterator&lt;ChatClientInt&gt; it = clientSet.iterator();
          while(it.hasNext()) {
              System.out.println(displayName + displayMsg + "\n");
          }       
      }
  
      public void run() {
          Scanner scanner = new Scanner(System.in);
          String  userName = "";
          try {
              this.serverObj =(ChatServerInt) new ChatServerImp();            
          } catch (RemoteException e) {
              e.printStackTrace();
          }
          //  Keep requesting until a name is submitted that is not already used.   
          // checking for the existence of a name and adding the name 
          // is done while locking the set of names.
          System.out.println("Please Enter a username\n");
  
          while(true) {           
              userName = scanner.nextLine();
              if(userName==null) {
                  return;
              }   
              clientName = userName;
              try {
                  serverObj.register(ChatClientImp.this);
                  listFromServer = serverObj.getClients();
                  clientSet.add(this);    
              } catch (RemoteException e) {
                  e.printStackTrace();
              }
  
              System.out.println("Hi" + " " + clientName + " " + "enter your message\n");
              String msg = scanner.nextLine();
              if(msg.equals("exit")) {
                  try {
                      serverObj.disconnect(this);
                      System.exit(0);
                  } 
                  catch (RemoteException e) {
                      e.printStackTrace();
                  }
              }//end if
  
              if((listFromServer.length) &gt; 1) {
                  System.out.println("list from client is" + " " + listFromServer.length + "going to try to send message.....\n");
                  try {
                      this.messageObj = new MessageImp(userName,  msg);
                      boolean result = this.sendMessage(messageObj);
                      if(result) {
                          System.out.print("sending result is:" + result + "\n");
                      } else {
                          System.out.println("sending was not successful\n");
                      }
                  } catch (RemoteException e1) {
                      System.out.println("Error tryiing to send message from the Run()\n");
                  } 
              } else {
                  System.out.println("There is no one else logged on\n");
              }
          }
      }
  
      public static void main(String[] args) throws RemoteException {
          String serverUrl= "rmi://localhost/ChatServer"; 
          try {
              ChatServerInt server = (ChatServerInt)Naming.lookup(serverUrl);
              Thread  thread = new Thread(new ChatClientImp());
              thread.start(); 
          } catch (MalformedURLException e) {
              e.printStackTrace();
          } catch (NotBoundException e) {
              e.printStackTrace();
          }   
      }
  }
  </code></pre>