WRITE A PROGRAM TO IMPLEMENT RMI IN JAVA FOR (I) A SINGLE CLIENT (II) MULTIPLE CLIENTS INTRODUCTION : RMI is one of the core Java APIs since version 1.1. It provides a framework for distributed computing. With RMI, separate parts of a single program can exist in multiple Java environments on multiple machines. To the client and server, the program operates much like it is local to their environment and within a single memory space. There are many cases where a distributed environment is beneficial. As applications grow large and complex they are more manageable, more performant, and more robust when they are distributed among multiple machines. Resources can be physically located where they make the most sense. Dedicated machines can be configured optimally to perform specialized operations. Heavy processing can be allocated to the best-suited hardware, centralized data servers can handle data processing, and web servers can just serve web pages. A large application can distribute the workload and achieve better efficiency and data isolation. RMI is a proven framework to design and implement a distributed application in a Java environment. Due to the multi-platform nature of Java, RMI is probably the best choice of API for this type of application. The client is defined as the application, which uses a remote object, and the server is defined as the machine which hosts the remote object. Communication is two way. Below is the standard simple diagram showing the relationship.
To both the client and server, the application appears to be local even though it is actually distributed among multiple Java environments. This is achieved by implementing interfaces, which define the methods, which can be invoked. The interfaces define the contract between the objects. What is actually passed back and forth are primitive data types (passed by value), remote references (objects which implement java.Remote), or copies of local objects (objects which implement java.io.Serializable). As one would expect, changes to the remote reference results in changes to the object; changes to the copy do not. Remote objects are listed in the rmiregistry of the server. A client will query the rmiregistry for an object by its handle and will receive a reference to the remote object. The client then invokes methods on the remote object. What actually is happening is that the client is invoking methods locally on the stub, which carries out the interaction. Likewise on the server side, the server interacts with the skeleton. The operations of the Remote Reference Layer and the Transport Layer are hidden from both sides. This allows different implementations of the Java Virtual Machine, which may be on different platforms, to integrate seamlessly. When the resources become large, extensive processing is required, or resources exist in multiple physical locations, then distributed objects are the way to go. The advantages include all of the power words that are commonly tossed around: scalability, maintainability, reliability, availability, extensibility, and manageability.
It provides an efficient network environment as the resources are only transmitted as needed and do not have to be loaded locally to each individual client. They can also be managed locally. The transmissions are much smaller than sending a complete formatted page for each query. This benefit would be magnified if the resources are large or need to be updated regularly.
CODE (SINGLE CLIENT):
RandomQuote.java import java.rmi.*; public interface RandomQuote extends Remote { public String getQuote() throws RemoteException; public String getQuotes(int n) throws RemoteException; }
QuoteServer.java import java.net.*; import java.rmi.*; public class QuoteServer { public static void main(String[] args) { try { QuoteServerImpl q = new QuoteServerImpl(); Naming.rebind("quotes", q); // sets the handle System.out.println("QuoteServer started and "+"awaiting connections."); } catch (RemoteException er) { System.out.println("Exception in QuoteServer.main: " + er); } catch (Exception err) { System.out.println("Exception occurred: " + err); } } }
QuoteServerImpl.java import java.rmi.*; import java.rmi.server.UnicastRemoteObject; import java.io.*; import java.util.*; public class QuoteServerImpl implements RandomQuote { ArrayList quotes = new ArrayList(); ArrayList chosen = new ArrayList(); String resources = "quote_r.txt"; //full path to your resources!! public QuoteServerImpl() throws RemoteException
{ UnicastRemoteObject.exportObject(this); } public String getQuote() throws RemoteException { if (quotes.size() == 0) { readQuotes(); } String output = getRandomQuote(); return output; } public String getQuotes(int n) throws RemoteException { if (quotes.size() == 0) { readQuotes(); } chosen.clear(); StringBuffer output = new StringBuffer(); String temp = ""; for (int i = 0; i < n; i++) { temp = getRandomQuote(); if (chosen.contains(temp)) { i--; } else { output.append(temp + "\n\n"); chosen.add(temp); } } return output.toString(); } private void readQuotes() { quotes.clear(); try { File f = new File(resources); FileReader fr = new FileReader(f); BufferedReader in = new BufferedReader(fr); String s = ""; while ((s = in.readLine()) != null) { quotes.add(s); } in.close(); } catch (IOException e) { System.out.println("ERROR: " + e);
quotes.add("Unable to access the Quotes " +"at this time. Please try again later."); } } private String getRandomQuote() { int n = quotes.size(); int selection = (int)Math.round(Math.random() * n); return (String)quotes.get(selection); } }
QuoteClient.java import java.rmi.*; public class QuoteClient { String quoteServer = "rmi://localhost/quotes"; public static void main(String[] args) { int num = 0; if (args.length > 0) { try { num = Integer.parseInt(args[0]); } catch (Exception e) { System.out.println("please enter a number as an argument"); System.exit(0); } } QuoteClient q = new QuoteClient(); if (num < 2) q.getQuote(); else if (num > 10) // enforcing a limit of 10 q.getQuotes(10); else q.getQuotes(num); } public void getQuote() { try { RandomQuote rq =(RandomQuote)Naming.lookup(quoteServer); System.out.println(rq.getQuote()); } catch (Exception e){System.out.println("ERROR: " + e);} }
public void getQuotes(int n) { try { RandomQuote rq =(RandomQuote)Naming.lookup(quoteServer); System.out.println(rq.getQuotes(n)); } catch (Exception e){System.out.println("ERROR: " + e);} } }
OUTPUT:
CODE (MULTIPLE CLIENTS):
BroadcastServer.java import java.rmi.*; public interface BroadcastServer extends Remote { void addBroadcastListener(BroadcastListener bl) throws RemoteException; void removeBroadcastListener(BroadcastListener bl) throws RemoteException; }
BroadcastServerApp.java import java.net.*; import java.rmi.*; public class BroadcastServerApp { public static void main(String args[]) { try { BroadcastServerImpl bsi; bsi = new BroadcastServerImpl(); Naming.rebind("BroadcastServer", bsi); } catch(Exception ex) { ex.printStackTrace(); } } }
BroadcastServerImpl.java import java.io.*; import java.rmi.*; import java.rmi.server.*; import java.util.*; public class BroadcastServerImpl extends UnicastRemoteObject implements BroadcastServer, Runnable { private Vector listeners; private Thread thread; public BroadcastServerImpl() throws RemoteException { listeners = new Vector(); thread = new Thread(this); thread.start(); } public void addBroadcastListener(BroadcastListener bl) throws RemoteException { listeners.addElement(bl); } public void removeBroadcastListener(BroadcastListener bl) throws RemoteException { listeners.removeElement(bl); } public void run() { try { InputStreamReader isr; isr = new InputStreamReader(System.in); BufferedReader br; br = new BufferedReader(isr); while(true) { String p = "Enter the message to be broadcast:"; System.out.println(p); String s = br.readLine(); if(s == null) { return; } sendMessage(s); } } catch(Exception ex) { ex.printStackTrace(); } }
protected void sendMessage(String message) { // v1 = a clone of the listeners vector, v2 = a new vector Vector v1, v2; synchronized(this) { v1 = (Vector)listeners.clone(); } v2 = new Vector(); // Broadcast the message to these listeners Enumeration e1 = v1.elements(); while(e1.hasMoreElements()) { BroadcastListener bl; bl = (BroadcastListener)e1.nextElement(); try { bl.receiveBroadcast(message); } catch(Exception ex) { v2.addElement(bl); } } // Remove listeners that caused exceptions Enumeration e2 = v2.elements(); while(e2.hasMoreElements()) { listeners.removeElement(e2.nextElement()); } } }
BroadcastListener.java import java.rmi.*; public interface BroadcastListener extends Remote { public void receiveBroadcast(String message) throws RemoteException; }
BroadcastListenerImpl.java import java.rmi.*; import java.rmi.server.*; public class BroadcastListenerImpl extends UnicastRemoteObject implements BroadcastListener {
public BroadcastListenerImpl() throws RemoteException { } public void receiveBroadcast(String message) throws RemoteException { System.out.println("Message = " + message); } }
BroadcastClient.java import java.rmi.*; public class BroadcastClient { private static BroadcastListenerImpl bli; public static void main(String[] args) { try { // Make rmi URL to BroadcastServer String broadcastServerURL; broadcastServerURL ="rmi://" + args[0] + "//BroadcastServer";
// Obtain a reference to that remote object BroadcastServer broadcastServer = (BroadcastServer)Naming.lookup(broadcastServerURL); bli = new BroadcastListenerImpl(); broadcastServer.addBroadcastListener(bli); } catch(Exception ex) { ex.printStackTrace(); } } }
OUTPUT:
Server Side Shell:
Server Side Shell:
Client Side Shell:
Server Side Shell:
Client Side Shell: