CPT402 Software Architectures Lab1

RMI

Hello RMI

Introduction

  • Client inputs its name
  • Server simply responds with a hello message with
    client’s name
    在这里插入图片描述
  • HelloRMI.rmiinterface contains code for remote interfaces
  • HelloRMI.server contains code for server program
  • HelloRMI.client contains code for client program

Implementation

Defining remote interfaces
  • An object becomes remote by implementing a remote interface java.rmi.Remote; each method of the interface declares java.rmi.RemoteException in its throws clause.
package rmiinterface;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RMIInterface extends Remote{
    String helloRMI(String clientName) throws RemoteException;
}
Implementing the remote server
  • An RMI server program needs to create the initial remote objects and export them to the RMI runtime, which makes them available to receive incoming remote invocations. This setup procedure can be either encapsulated in a method of the remote object implementation class itself or included in another class entirely.
    The setup procedure should do the following:

    • Create and install a security manager
    • Create and export one or more remote objects
    • Register at least one remote object with the RMI registry (or with another naming service, such as a service accessible through the Java Naming and Directory Interface) for bootstrapping purposes
  • Any methods defined in the implementation class or defined in non-remote interfaces implemented by the class are not available to that receiver.
    (In this example, the receiver of the reference to an instance of this RMIServer class would not see the RMIServer constructor, its main method, or its implementation of any methods of java.lang.Object.)

  • Security Manager protects access to system resources from untrusted downloaded code running within the Java virtual machine.
    A security manager determines whether downloaded code has access to the local file system or can perform any other privileged operations.

  • If an RMI program does not install a security manager, RMI will not download classes (other than from the local class path) for objects received as arguments or return values of remote method invocations. This restriction ensures that the operations performed by downloaded code are subject to a security policy.

  • The static UnicastRemoteObject.exportObject method exports the supplied remote object so that it can receive invocations of its remote methods from remote clients. The second argument, an int, specifies which TCP port to use to listen for incoming remote invocation requests for the object. It is common to use the value zero, which specifies the use of an anonymous port. The actual port will then be chosen at runtime by RMI or the underlying operating system.
    However, a non-zero value can also be used to specify a specific port to use for listening. Once the exportObject invocation has returned successfully, the ComputeEngine remote object is ready to process incoming remote invocations.

  • The java.rmi.registry.Registry remote interface is the API for binding (or registering) and looking up remote objects in the registry.

  • The java.rmi.registry.LocateRegistry class provides static methods for synthesizing a remote reference to a registry at a particular network address (host and port). These methods create the remote reference object containing the specified network address without performing any remote communication.

  • The no-argument overload of LocateRegistry.getRegistry synthesizes a reference to a registry on the local host and on the default registry port, 1099. You must use an overload that has an int parameter if the registry is created on a port other than 1099.

package server;

import java.rmi.RemoteException;
import rmiinterface.RMIInterface;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;

/**
 * This class has a main method for setting up the server
 * this class also implements interface, so can be used for a remote object
 * @author colin
 */
public class RMIServer implements RMIInterface{ 
    // server instancs, make it avaliable to clients
    @Override
    public String helloRMI(String clientName) throws RemoteException {
        return "Hello "+clientName;
    }
    
    // this main method is used to start the RMI Server
    // this method is not a remote method (cause it is static)
    // setup procedure
    public static void main(String[] args) throws RemoteException {

        // Creating and Installing a Security Manager
//        if (System.getSecurityManager()==null){
//            System.setSecurityManager(new SecurityManager());
//        }

        // == rmiregistry& command on MacOS
        LocateRegistry.createRegistry(1099);
        
        try {
            // initial remote object, 
            RMIInterface myHello = new RMIServer();
            
            // Now we need export it to the RMI runtime 
            // to receive incoming remote invocations
            
            // .exportObject might throw RemoteException
            // returns a stub for the exported remote object
            // ! the type of stub must be Interface 
            // because the stub only implements the remote interfaces
            RMIInterface stub = (RMIInterface) UnicastRemoteObject.exportObject(myHello, 0);
            
            // Registry: a simple remote object naming server
            // get a reference to a registry on the local host
            Registry registry = LocateRegistry.getRegistry();
            // adds the name to the RMI registry running on the server. 
            String name = "Hello program";
            registry.rebind(name, stub);
            
            System.out.println("Server started");
        } catch (Exception e) {
            System.err.println("RMI Server exception:");
            e.printStackTrace();
        }
    }
}
Implementing the clients
package client;

import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import rmiinterface.RMIInterface;

public class RMIClient {
    public static void main(String[] args) {
//        if (System.getSecurityManager()==null){
//            System.setSecurityManager(new SecurityManager());
//        }
        
        try {
            String name = "Hello program";
            // get registry from a remote server 
            Registry registry = LocateRegistry.getRegistry("127.0.0.1",1099);
            //get a reference of a remote object
            RMIInterface myHellp = (RMIInterface)registry.lookup(name);
			// invoke method of that remote object
            String message = myHellp.helloRMI("Colin");
            System.out.println(message);

        } catch (Exception e) {
            System.err.println("Client say hello exception");
            e.printStackTrace();
        }
    }
}

Starting the application

IDE(NetBeans) Version
  • Build project
  • Start server:
    • Run File (RMIServer)
  • Start client:
    • Run File (RMIClient)
Command Line(MacOS) Version
  • Build project
  • Start registry:
    • rmiregistry& :This command has the same effect as the LocateRegistry.createRegistry(1099);
      You can ignore this if you have createRegistry() in Java code.
    • Need to be executed in the same folder as your classes if classpath not set.
HelloRMI/build/classes$ rmiregistry&
[1] 1456

It will return its PID number.

HelloRMI/build/classes$ lsof -i | grep 1456
rmiregist 1456 colin    9u  IPv6 0x9413eb7ad9360e ...

We can kill it like:

HelloRMI/build/classes$ kill -9 1456
  • Start server:
HelloRMI/build/classes$ java HelloRMI.server.RMIServer
  • Start client:
HelloRMI/build/classes$ java HelloRMI.client.RMIClient

If you installed a security manager in your program, you need have a server policy server.policy under the same folder as you class file.

grant codeBase "file:/Users/colin/Developer/java/HelloRMI/build/classes/" {
    permission java.security.AllPermission;
    permission java.net.SocketPermission "127.0.0.1:1099","connect,resolve";
};

And execut like this:

HelloRMI/build/classes$ java -Djava.security.policy=server.policy server.RMIServer

light-weight calculator system

Introduction

Functionalities provided by the server

  • public int add(int a, int b);
  • public int compare(int a, int b);
    • a > b return 1
    • a = b return 0
    • a < b return -1
  • public boolean equal(Group a, Group b);
    • Class Group contains three int attributes x, y
      and z

在这里插入图片描述

  • RMIcalculator.rmiinterface contains code for remote interfaces
  • RMIcalculator.server contains code for server program
  • RMIcalculator.client contains code for client program
  • RMIcalculator.bean contains helper classes

Implementation

Defining help classes

Passing Objects in RMI

  • Arguments to or return values from remote methods can be of almost any type, including local objects, remote objects, and primitive data types. More precisely, any entity of any type can be passed to or from a remote method as long as the entity is an instance of a type that is a primitive data type, a remote object, or a serializable object, which means that it implements the interface java.io.Serializable.
package bean;

import java.io.Serializable;

public class Group implements Serializable{
    int x;
    int y;
    int z;

    public Group(int x, int y, int z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getZ() {
        return z;
    }
    
}
Defining remote interfaces
package rmiinterface;

import bean.Group;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface CalInterface extends Remote{
    public int add(int a, int b) throws RemoteException;
    public int compare(int a, int b) throws RemoteException;
    public boolean equal(Group a, Group b) throws RemoteException;
}
Implementing the remote server

This time, the implementation of remote Interface and the setup of the server are in two classes, hope it‘s easier to understand.

package server;

import bean.Group;
import java.rmi.RemoteException;
import rmiinterface.CalInterface;

public class CalClass implements CalInterface{
    @Override
    public int add(int a, int b) throws RemoteException {
        return a+b;
    }

    @Override
    public int compare(int a, int b) throws RemoteException {
        return a>b ? 1 : a==b ? 0 : -1;
    }

    @Override
    public boolean equal(Group a, Group b) throws RemoteException {
        return a.getX()==b.getX() && a.getY()==b.getY()&& a.getZ()==b.getZ();
    }

}
package server;

import java.rmi.RemoteException;
import rmiinterface.CalInterface;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;

public class Server {

    public static void main(String[] args) {

//        if (System.getSecurityManager()==null){
//            System.setSecurityManager(new SecurityManager());
//        }

        int portid = 1099;
        try {
            LocateRegistry.createRegistry(portid);
            System.out.println("Using port: "+portid);
        } catch (RemoteException ex) {
            System.out.println("createRegistry Error, might be Port occupied:"+portid);
            ex.printStackTrace();
        }
        
        String name = "my Calculator";
        CalClass cal = new CalClass();
        try {
            CalInterface stub = (CalInterface)UnicastRemoteObject.exportObject(cal, 0);
            Registry registry = LocateRegistry.getRegistry();
            registry.rebind(name, stub);
            System.out.println("Server started~");
        } catch (RemoteException ex) {
            ex.printStackTrace();
        }
    }
       
}
Implementing the clients
package client;

import bean.Group;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import rmiinterface.CalInterface;

public class CalClient {

    public static void main(String[] args) {

//        if (System.getSecurityManager()==null){
//            System.setSecurityManager(new SecurityManager());
//        }
        try {
            String name = "my Calculator";
            Registry registry = LocateRegistry.getRegistry();
            CalInterface myCal = (CalInterface)registry.lookup(name);
            
            System.out.println("2+3 = "+myCal.add(2, 3));
            System.out.println("2 compare 3: "+myCal.compare(2, 3));
            System.out.println("2 compare 3: "+myCal.compare(3, 3));
            System.out.println("2 compare 3: "+myCal.compare(3, 2));
            
            Group a = new Group(1, 2, 3);
            Group a2 = new Group(1, 2, 3);
            Group b = new Group(3, 2, 1);
            System.out.println("Group a & a2: "+myCal.equal(a, a2));
            System.out.println("Group a & b: "+myCal.equal(a, b));
        } catch (Exception e) {
            System.err.println("Client calculator exception");
            e.printStackTrace();
        }
    }
    
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值