Carnegie Mellon University 95-702 Organizational Communications and Distributed Object Technologies Lab 2 is due at the start of class on June 13, 2007. In the first part of this homework you will work with UDP and TCP over IP. In the second part you will work with low level RMI in Java. PART I UDP and TCP From Chapter 4 of the Coulouris text (1) On pages 138 and 139 of the Coulouris text, two short programs are presented. Make modifications to the UDPClient program and the UDPServer program so that the client may ask the server to perform simple integer arithmetic. You only need implement addition of primitive integers. You may assume that you have a well behaved user and all input is correct. The execution of the client program will look like the following: java UDPClient 100 + 234 Reply:334 Submit paper copies of all of your documented source code as well as a few screen shots showing your client and server interacting. (2) On pages 142 and 143 of the Coulouris text, two short programs are presented. Make modifications to the TCPClient program and the TCPServer program so that the client may ask the server to perform simple integer arithmetic. You only need implement addition of primitive integers. You may assume that you have a well behaved user and all input is correct. The execution of the client program will look like the following: java TCPClient 100 + 234 Reply:334 Submit paper copies of all of your documented source code as well as a few screen shots showing your client and server interacting. Part II Low Level RMI The following collection of programs illustrate low level remote method invocation (RMI). That is, we are not yet working with Java RMI. We are implementing a simple RMI system with Java. (1) Your first task is to get these programs running and to study them closely. The terms "skeleton" and "stub" are used and you should understand exactly what kind of objects these terms refer to. Get the programs working in two separate Eclipse projects as demonstrated in class. The interface file (Person.java) must be placed on the server side as well as the client side. Eclipse will present two different console windows - one for the client and one for the server. The red box on the console window may be used to stop the server process. Submit paper copies of all of your documented source code as well as a few screen shots showing your client and server interacting. Your documentation should explain what each part of this little system is for. The following questions ask you to build a distributed object server, a registry and a client. Registry located at port 9090 / \ lookup / \bind / \ Client makes a call Object server at port 9000 on the registry -----rmi----- makes call on registry and then calls and then services calls methods on remote on an object object (2) Write a new Java class called RemoteObjectReference that implements Serializable. This class will encapsulate the private fields found in Figure 4.13, on page 154, of the Coulouris text. This class will have getter and setter methods for each field and a small main routine used as a test driver. The "interface of object" field will be defined as a String object. The other three fields are simple integers. This class will be present on the client, object server and registry server as defined below. Submit paper copies of all of your documented source code. (3) Write a new Java class called RequestReplyMessage that implements Serializable. This class will encapsulate the private fields found in Figure 4.16, on page 157, of the Coulouris text. Note that a RequestReplyMessage object has a RemoteObjectReference member. This must be the same class defined in the previous step. Setter and getter methods need to be defined. Note that a RemoteObjectReference object contains enough information to specify a remote object. The RequestReplyMessage contains, in addition, information on the method that will be invoked (or was invoked) on that object as well as an array of bytes specifying the arguments to or return values from the method. XXXX This class will be present on the client and object server only. You need not include it on the registry. (4) Create three Eclipse projects named "ClientProject", "ObjectServerProject", and "RegistryServerProject". (5) The ClientProject will contain the following Java classes: * PersonClient.java PersonClient creates a Binder_Stub object so that it may make lookup calls on the registry. It will call lookup("Mike") and receive a RemoteObjectReference object from the registry. PersonClient will then create a Person_Stub object with the RemoteObjectReference as a parameter to the Person_Stub constructor. It will then make calls on the stub to retrieve the name and age in the remote object. * Binder_Stub.java This class implements the Binder interface and contains bind and lookup methods. The client only makes use of the lookup method. * Binder.java Defines the lookup method as taking a string argument and returning a RemoteObjectReference value. Defines the bind method that takes a string and a RemoteObjectReference as input. Its return type is void. * Person_Stub.java This class implements the Person interface and contains getAge and getName methods. It creates a RequestReplyMessage from the information found in the RemoteObjectReference and sends this message to a socket. It reads a RequestReplyMessage from the socket, extracts bytes, and returns either the name or age in the remote object. * Person.java This is the same interface as shown below. XXXX * RemoteObjectReference.java and RequestReplyMessage.java. See above for a description of these classes. (6) The RegistryServerProject will contain the following classes: * Binder_Servant.java This class implements Binder and implements the registry with a TreeMap. * Binder.java See above for a description. * Binder_Skeleton.java The serve method of this class is written like the serve method in Person_Skeleton shown below. It reads String objects from sockets and makes calls on its Binder_Servant. For lookups, it writes a RemoteObjectReference object to the socket. Nothing is written for calls on bind. * BinderServer.java This class starts up the registry. It creates a Binder_Servant and passes that servant to its new Binder_Skeleton and calls serve. * RemoteObjectReference .java This class is described above. (7) The ObjectServerProject contains the follwing java classes: * Binder_Stub.java see above * Binder.java see above * Person_Servant.java This class implements Person and is shown below. * Person_Skeleton.java This class has a server method that reads RequestReplyMessages and writes RequestReplyMessages. In between the reading and writing it makes a call on the Person_Servant object. * Person.java see below. * PersonServer.java This class creates a Person object and a RemoteObjectReference. It uses the Binder_Stub to make a bind call on the registry. It creates a Person_Skeleton object and asks it to server. * RemoteObjectReference.java see above * RequestReplyMessage.java see above Submit paper copies of all of your documented source code. Show a few screen shots that demonstrate your system working. // file: Interface.java on both the client and server side public interface Person { public int getAge() throws Exception; public String getName() throws Exception; } // file: Person_Stub.java found only on the client side import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.net.Socket; public class Person_Stub implements Person { Socket socket; ObjectOutputStream o; ObjectInputStream i; public Person_Stub() throws Exception { } public int getAge() throws Exception { socket = new Socket("localhost",9000); o = new ObjectOutputStream(socket.getOutputStream()); o.writeObject("age"); o.flush(); i = new ObjectInputStream(socket.getInputStream()); int ret = i.readInt(); socket.close(); return ret; } public String getName() throws Exception { socket = new Socket("localhost",9000); o = new ObjectOutputStream(socket.getOutputStream()); o.writeObject("name"); o.flush(); i = new ObjectInputStream(socket.getInputStream()); String ret = (String)(i.readObject()); socket.close(); return (String)ret; } } // file: PersonClient.java exists only on the client side public class PersonClient { public static void main(String args[]) { try { Person p = new Person_Stub(); int age = p.getAge(); System.out.println("Age = " + age); String name = p.getName(); System.out.println(name + " is " + age + " years old"); } catch(Exception t) { t.printStackTrace(); System.exit(0); } } } // file: Person_Skeleton.java exists only on the server side import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.net.Socket; import java.net.ServerSocket; public class Person_Skeleton { Person myServer; public Person_Skeleton(Person s) { myServer = s; } public void serve() { try { ServerSocket s = new ServerSocket(9000); while(true) { Socket socket = s.accept(); ObjectInputStream i = new ObjectInputStream(socket.getInputStream()); String method = (String)i.readObject(); if(method.equals("age")) { int a = myServer.getAge(); ObjectOutputStream o = new ObjectOutputStream(socket.getOutputStream()); o.writeInt(a); o.flush(); } else if(method.equals("name")) { String n = myServer.getName(); ObjectOutputStream o = new ObjectOutputStream(socket.getOutputStream()); o.writeObject(n); o.flush(); } } } catch(Exception t) { System.out.println("Error " + t); System.exit(0); } } } // file: Person_Servant.java exists only on the server side public class Person_Servant implements Person { int age; String name; public Person_Servant(String n, int a) { name = n; age = a; } public int getAge() { return age; } public String getName() { return name; } } // file: PersonServer.java exists only on the server side public class PersonServer { public static void main(String args[]) { Person p = new Person_Servant("Mike",23); Person_Skeleton ps = new Person_Skeleton(p); ps.serve(); } }