RMI: 远程方法调用(Remote Method Invocation),用于不同虚拟机之间的通信,这些虚拟机可以在不同的主机上、也可以在同一个主机上;一个虚拟机中的对象调用另一个虚拟上中的对象的方法。
RMIDemo
服务端组成的三个部分
创建一个继承java.rmi.Remote
的接口(RMIInterface
),定义需要远程调用的函数(HelloWorld()
)
一个实现此接口的类(RemoteHelloWorld
),在服务端实现接口定义的代码。
一个主类(RMIServer
)用于创建Registry
,绑定类示例
RMIInterface
1 2 3 4 5 6
| import java.rmi.Remote; import java.rmi.RemoteException;
public interface RMIInterface extends Remote { String HelloWorld() throws RemoteException; }
|
RemoteHelloWorld
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject;
public class RemoteHelloWorld extends UnicastRemoteObject implements RMIInterface{
protected RemoteHelloWorld() throws RemoteException { super(); }
@Override public String HelloWorld() throws RemoteException { return "HelloWorld"; } }
|
RMIServer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import java.net.MalformedURLException; import java.rmi.AlreadyBoundException; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry;
public class RMIServer { public static final String RMIHost = "192.168.47.128"; public static final int RMIPort = 1099; public static final String RMIName = "rmi://" + RMIHost + ":" + RMIPort + "/HelloWorld";
public static void main(String[] args) throws RemoteException, MalformedURLException, AlreadyBoundException { LocateRegistry.createRegistry(RMIPort); Naming.bind(RMIName, new RemoteHelloWorld()); System.out.println("RMIServer created, ip address:" + RMIName); }
}
|
客户端
RMIClient
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException;
public class RMIClient {
public static void main(String[] args) throws MalformedURLException, NotBoundException, RemoteException { RMIInterface rt = (RMIInterface) Naming.lookup("rmi://192.168.47.1:1099/HelloWorld"); String result = rt.HelloWorld(); System.out.println(result); } }
|
运行测试
服务端47.1
客户端47.128
47.128
向47.1
第一次握手之后,客户端向服务端发送一个Call
数据包,服务端回一个ReturnData
数据包
在ReturnData
数据包中,ac ed
往后为反序列化内容。
修改客户端代码rebind()
HelloWorld
方法
1 2 3 4 5 6 7 8 9
| public class RMIClient {
public static void main(String[] args) throws MalformedURLException, NotBoundException, RemoteException { Naming.rebind("rmi://192.168.47.1:1099/HelloWorld",new RemoteHelloWorld()); RMIInterface rt = (RMIInterface) Naming.lookup("rmi://192.168.47.1:1099/HelloWord"); String result = rt.HelloWorld(); System.out.println(result); } }
|
报错如下
只有源地址是本地才可调用rebind
,bind
,unbind
。list
,lookup
可远程调。