java rmi 初探

RMI 过程方法调用
能够让在某个Java虚拟机上的对象像调用本地对象一样调用另一个java 虚拟机中的对象上的方法。

RPC 远程过程调用
用于一个进程调用另一个进程(很可能在另一个远程主机上)中的过程,从而提供了过程的分布能力。Java 的 RMI 则在 RPC 的基础上向前又迈进了一步,即提供分布式对象间的通讯。

RMI 服务注册步骤
1. 实现接口或者继承相关类
Remote 接口
表明接口允许被远程访问

UniCastRemoteObject 类
表示该具体服务对象可以被输出到客户端,供客户端调用

实现以上接口或者类的对象才能用作RMI对象

  1. 编写服务端注册代码

代码示例:

接口 Fly

public interface Fly extends Remote{
    String fly(String words) throws RemoteException;
}

接口实现 HelloFly

public class HelloFly extends UnicastRemoteObject implements Fly{

    private static final long serialVersionUID = 1L;

    protected HelloFly() throws RemoteException {
        super();
    }

    @Override
    public String fly(String words) throws RemoteException {
        System.out.println("hello fly " + words + "in server service");
        return "hello fly" + words;
    }

}

服务端注册服务代码

public class RMIServer {
    public static void main(String[] args) throws RemoteException{
        try {
            LocateRegistry.createRegistry(1099);
            Fly fly = new HelloFly();
            Naming.bind("rmi://localhost/fly01", fly);
            System.out.println("HelloServer start success");
        } catch (MalformedURLException | AlreadyBoundException e) {
            e.printStackTrace();
            System.out.println("bind service fail.");
        }
    }

}

客户端获取服务,进行调用代码

public class RMIClient {
    public static void main(String[] args) {
        Fly fly;
        try {
            fly = (Fly)Naming.lookup("rmi://localhost/fly01");
            System.out.println(fly.fly("good jobs"));
        } catch (MalformedURLException | RemoteException | NotBoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

RMI远程调用步骤
Client<–>stub<–>[socket NETWORK]<–>skeleton<–>Server
在jdk1.2之后,skeleton就被合并到server中了
Client<—>stub<—>[NETWORK]<—>Server_with_skeleton

RMI远程调用步骤:
1. 客户对象调用客户端辅助对象stub上的方法
2. 客户端辅助对象打包调用信息(变量,方法名),通过网络发送给服务端辅助对象
3. 服务端辅助对象skeleton将客户端辅助对象发送来的信息解包,找出真正被调用的方法以及该方法所在对象
4. 调用真正服务对象上的真正方法,并将结果返回给服务端辅助对象
5. 服务端辅助对象将结果打包,发送给客户端辅助对象
6. 客户端辅助对象将返回值解包,返回给客户对象
7. 客户对象获得返回值

客户端获取服务器端远程对象的拷贝 存根 stub
服务端本身存在的远程对象 骨架 skeleton

以上两者都可以称为远程对象的代理。

RMIRegistry 远程服务对象的注册中心
启动
LocateRegistry.createRegistry(1099);
作用:
1. 服务端,将远程对象注册到注册中心中
2. 客户端,通过url得到远程对象在本地的代理,即stub.

使用手动命令行实现 java rmi

使用rmic xxx.class 生成xxx_stub.class文件,该存根文件是远程对象在本地的代理,通过服务端代码xxx.java生成(现在已经过时)

打开注册机服务。java_home/bin/rmiregistry

运行服务端绑定远程服务程序

Fly fly = new HelloFly();
Naming.bind("rmi://localhost/fly01", fly);

客户端使用远程服务

fly = (Fly)Naming.lookup("rmi://localhost/fly01");
System.out.println(fly.fly("good jobs"));

如果出现连接拒绝,可能是因为rmiregistry或者运行服务端程序被终止了。

  • 遇到了问题,运行的时候报错 java.lang.ClassNotFoundException: com.zhb.rmi.HelloFly_Stub
  • HelloFly_Stub已经在同级目录下,classpath中添加了../../src/main/java路径
  • 解决:重启rmiregistry服务就可以了。
  • ps:
  • 1.java com.zhb.rmi.RMIServer 启动之后,不要关闭它,启动rmiregistry后也不能关闭它。
  • 启动另外一个窗口运行client.
  • 2.classpath 可以不添加额外的路径,如果stub和server在同一级目录的话。
  • @author haibingCastle
    *

参考博文,感谢前辈分享

http://haolloyin.blog.51cto.com/1177454/332426/
http://blog.csdn.net/a19881029/article/details/9465663
http://blog.csdn.net/xinghun_4/article/details/45787549
http://www.jianshu.com/p/2c78554a3f36

你可能感兴趣的:(java,java)