- Internetprogrammering 98/99 -

RMI: Meddelandesystem baserat på RMI

Ungefär samma meddelandesystem som det vi gjorde baserat direkt på socketar implementeras mha RMI.
Kommandona som är implementerade i servern beskrivs av  interfacetMessageBoardInterface.

Serverns gränssnitt

En beskrivning av dom meddelanden som klienter kan använda för att kommunicera med servern.
import java.rmi.*;

interface MessageBoardInterface extends Remote {

 //Skicka meddelandet message till klienten med identifikationen clientID
 public void passMessageTo(String message, String clientID) throws RemoteException;

 //Skicka message till alla klienter
 public void broadcast(String message) throws RemoteException;

 //Returnera en lista med alla klienters användarnamn
 public String [] getClientNames() throws RemoteException;

 //Returnera en lista med alla klienters användaridentiteter
 public String [] getClientIDs() throws RemoteException;

 //Anslut en klient med namnet userName och objekt messageReceiver för att ta emot meddelanden från andra/servern. Returnerar en användaridentitet.
 public String addClientWithMessageReceiver(String userName, MessageReceiverInterface messageReceiver) throws RemoteException;

}

Klienternas gränssnitt för meddelandemottagning

Ett meddelande skickas från annan klient, via servern, till mottagare genom att ett objekt som implemneterar följande gränssnitt anropas.
import java.rmi.*;

interface MessageReceiverInterface extends Remote {
 public void message(String message)throws RemoteException;
}

Klienternas klass som implementerar meddelandemottagning

import java.rmi.*;
import java.rmi.server.*;

public class MessageReceiver extends UnicastRemoteObject implements MessageReceiverInterface {
 public MessageReceiver()  throws RemoteException {
  super();
 }

 public void message(String message) throws RemoteException {
  System.out.println("Message: " + message);
 }
}

Server

import java.rmi.*;
import java.rmi.server.*;
import java.util.*;

public class MessageBoardServer extends UnicastRemoteObject implements MessageBoardInterface {
 /* clientCatalogue är en katalog med alla användare (användarnamn är nyckel) och deras respektive objekt som väntar på att meddelande skall skickas till dem (meddelandeobjektet är värde i katalogen)
 */
 Hashtable clientsCatalogue = new Hashtable();

 public MessageBoardServer() throws RemoteException
 {
  super();
 }

 public void passMessageTo(String message, String clientID) throws RemoteException {
  /* Skicka meddelandet message till användaren med namnet clientID */
  MessageReceiverInterface messageReceiver = ((MessageReceiverInterface) clientsCatalogue.get(clientID));

  if(messageReceiver != null) {
   try {
    messageReceiver.message(message);
   }
   catch(Exception e) {}
  }
 }

 public void broadcast(String message) throws RemoteException{
  String [] clients = getClientIDs();
  for(int i = 0; i < clients.length; i++) passMessageTo(message, clients[i]);
 }

 public String [] getClientNames() throws RemoteException {
  /*Returnera alla klienters namn */
  String[] s;
  s = new String[clientsCatalogue.size()];
  int i = 0;
  for(Enumeration e = clientsCatalogue.keys(); e.hasMoreElements(); i++)
   s[i] = (String) e.nextElement();
  return s;
 }

 public String [] getClientIDs() throws RemoteException {
  /*Returnera alla klienters ID */
  //I den här versionen använder vi användarnamn som ID så vi returnerar helt enkelt alla användarnamn
  return getClientNames();
 }

 public String addClientWithMessageReceiver(String userName, MessageReceiverInterface messageReceiver) throws RemoteException {
  /*Lägg in användaren i katalogen i registrera hans/hennes meddelandeobjekt.
  Returnera slutligen det id som användaren fått sig tilldelat.*/
  clientsCatalogue.put(userName, messageReceiver);

  //I den här versionen använder vi användarnamnet som id
  return userName;
 }

 public static void main(String [] args) {
  // System.setSecurityManager(new RMISecurityManager());
  try {
   MessageBoardServer server = new MessageBoardServer();
   Naming.rebind("messageboardserver", server);
   System.out.println("Message Board Server ready.");
  }
  catch(RemoteException re) {
   System.out.println("RemoteException in MessageBoardServer.main: " + re);
  }
  catch(Exception e) {
   System.out.println("Exception in MessageBoardServer.main: " + e);
  }
 }
}

Klient

import java.rmi.*;
import java.io.*;

public class MessageBoardClient{

 public static void main(String [] args) {
  String name;
  //Första argumentet vid start av klienten ger aktuell klients användarnamn
  //Om inget argument ges använder vi användarnamnet vi får från System.getProperty(...)
  if(args.length >= 1) name = args[0];
  else name = System.getProperty("user.name");

  System.out.println("Client with name: " + name + " about to register at server ...");
  // System.setSecurityManager(new RMISecurityManager());
  try {
   MessageBoardInterface server = (MessageBoardInterface) Naming.lookup("messageboardserver");

   MessageReceiverInterface messageReceiver = new MessageReceiver ();
   String id = server.addClientWithMessageReceiver(name, messageReceiver);

   System.out.println("... and is now registered with id: " + id);

   //Mycket enkelt test
   String line = "";
   BufferedReader in;
   in = new BufferedReader(new InputStreamReader(System.in));
   for(;;){
        System.out.print(">");
        try {
            line = in.readLine();
        }
        catch(IOException e) {};
        if(line.equals("quit")) {
             System.exit(0);
        }
        else server.broadcast(line);
   }
  }
  catch(Exception e) {
   System.out.println("Exception in MessageBoardClient.main: " + e);
  }
 }
}

Kompilera och kör

Kompilera med javac och rmic samt kör precis på samma sätt som i tidigare exempel.

^ Upp till kursens hemsida.


Sidansvarig: <bjorne@nada.kth.se>
Senast ändrad 22 april 1999