最近想学习一下Web底层机制,也不知道从哪里开始看起。 找了一本差不多的书《Java网络高级编程》,看到RMI这一块,发现自己看不明白,就网络上各处寻找资料,鼓捣了一晚上,终于明白了怎么回事。发出来显摆OR丢人一下
。
大神们手下留情啊。 上次被弄了一个新手帖,悲剧死了。。。
Java Remote Method Invocation ( RMI -- Java远程方法调用
)
允许您使用
Java
编写分布式对象
RMI(远程方法调用)的组成
一个正常工作的RMI
系统由下面几个部分组成:
1、
远程服务的接口定义
2、
远程服务接口的具体实现
3、
桩(Stub
)和框架(
Skeleton
)文件
4、
一个运行远程服务的服务器
5、
一个RMI
命名服务,它允许客户端去发现这个远程服务
6、
类文件的提供者(一个HTTP
或者
FTP
服务器)
7、
一个需要这个远程服务的客户端程序
RMI(远程方法调用)的工作原理
RMI系统结构,在客户端和服务器端都有几层结构。
方法调用从客户对象经占位程序(Stub)
、远程引用层
(Remote Reference Layer)
和传输层(
Transport Layer
)向下,传递给主机,然后再次经传 输层,向上穿过远程调用层和骨干网(
Skeleton
),到达服务器对象。 占位程序扮演着远程服务器对象的代理的角色,使该对象可被客户激活。 远程引用层处理语义、管理单一或多重对象的通信,决定调用是应发往一个服务器还是多个。传输层管理实际的连接,并且追追踪可以接受方法调用的远程对象。服务器端的骨干网完成对服务器对象实际的方法调用,并获取返回值。返回值向下经远程引用层、服务器端的传输层传递回客户端,再向上经传输层和远程调用层返回。最后,占位程序获得返回值。
要完成以上步骤需要有以下几个步骤:
1、
生成一个远程接口
2、
实现远程对象(
服务器端程序
)
3、
编写服务器程序 、注册远程对象、启动远程对象
4、
编写客户程序
RMI的实现原理
1、
调用者(Client
)以通常方法
obj.invoke()
调用一个本地接口的远程实现类的实例
2、
顾客Stub
的功能把有关的远程调用参数封装为一个消息包(数据包)或者一组消息包,第一步调用访问的远程服务的地址(
rmi://localhost:1099/
)、对象(
obj
)、调用方法(
invoke()
)及其参数都包含在这条消息中
3、
调用者(Client
)本地
RMI Runtime
将这条消息发送给对应的服务器地址(
rmi://localhost:1099/
)
RMI Runtime
(
rmi
协议基于
tcp/ip
协议),服务器端
RMI Runtime
寻找绑定远程对象的进程(某个
javaw.exe
),然后调用这个进程中绑定的远程对象的指定方法,执行之后,将执行结果返回给调用者(
Client
)(其中的运行涉及到序列化和反序列化,因此为了平台兼容性每个有关
java
类都最好实现序列化。经常看到有人压制序列号警告而不是添加一个序列化
ID
。。。)
4、
调用者(Client
)
RMI Runtime
接受到返回的结果,然后将此结果反序列化并且返回到调用方法。
在以上回避了一个重要问题,即Client
怎么知道并调用
Server
上某个远程对象呢?这里就用到了命名服务。命名服务(
Name Service
)是分布式系统基本的公共服务。
Java
远程方法调用利用
RMI
机制提供命名服务。命名是给一个对象起一个名字,也就是就是说把名字绑定(
binding
)到该对象上,也就是以
Key|Value
的
mapping
存储在
RMI
上的,它的目的就是用人们容易理解的名字代替计算机中人们不易理解的存储表示对象。
Client
通过
Server
上的某个
key(String
类型
)
获取指定的
value(Object
类型
)
,这个
value
是一种实现类,这个实现类所实现的规范或者说是接口本地一定要有,然后本地调用的就是这个接口的远程实现了。由此可见,
RMI
的命名服务在
RMI
服务器端为
RMI
服务器提供者提供发布
RMI
服务对象的功能,在
RMI
客户端为
RMI
客户提供搜索远程
RMI
服务对象的功能
实例
1、远程接口
该接口定义了一个方法,用于提供远程服务
package net.sulin.test.rmi;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Upper extends Remote {
public String UpperString(String param)
throws RemoteException ;
}
|
2、
实现远程对象(
服务器端程序
)
用来创建一个
Upper对象,然后由远程客户端获取
package net.sulin.test.rmi;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class UpperImpl extends UnicastRemoteObject
implements Upper {
private static final long
serialVersionUID = 806571139035814115L;
protected UpperImpl() throws RemoteException {
super();
}
@Override
public String UpperString(String param)
throws RemoteException {
System.out.println("remote invoking successfully");
return param.toUpperCase();
}
}
|
3
、编写服务器程序 、注册远程对象、启动远程对象
代码:远程对象的注册类 该类应该在服务器端执行 执行之后, 该机器将变为RMI
服务器 客户端可以通过正确的
url
来访问;服务器上的远程对象;执行对外报露的方法
package net.sulin.test.rmi;
import java.rmi.Naming;
public class ServerBad {
public static void main(String[] args) throws Exception {
UpperImpl upp = new UpperImpl();
Naming.rebind("upper", upp);
System.out.println("Bind successfully");
}
}
|
运行该服务端代码后,将会注册一个远程服务对象
4
、编写客户程序
代码首先获取一个远程对象,然后如同本地调用一样,调用远程对象中的方法。
package net.sulin.test.rmi;
import java.rmi.Naming;
public class Client {
public static void main(String[] args) throws Exception {
Upper upper = (Upper) Naming.lookup("upper");
System.out.println(upper.UpperString("aaaaaa"));
}
}
|
这些之后,还不行的。
还需要做下列的一系列事情:
1、 使用
rmic
编译一个能被
RMI
服务使用的
clsss
文件
这个clsss
就是需要远程调用的类。在这里就是
UpperImpl.class
了
记住,先javac UpperImpl.java
、 再
rmic UpperImpl
2、 然后就是启动
rmi
服务了。 打开控制台,输入
start rmiregistry
,再按回车就
OK
了
最后一步就是启动服务类
ServerBad
了
这里是最容易出错的,参见下面注意事项。
注意:
如果提示找不到Stub
类,这个需要用下面的命令来运行
java.exe
-Djava.rmi.server.codebase
=file:/
*_stub.class
/
ServerBad
*_stub.clss就是第一步生成的
*_stub.class
的文件绝对路径
3、
启动你的客户端程序吧
你难道就不好奇我的服务类为什么是
Server
Bad,
因为我感觉这种方法太麻烦了。。。
还有一种更简单的方法,使用
java.rmi.registry
.Registry动态注册一个绑定指定端口(可选,默认
1099
)的
rmi
服务。
服务端的类可以换为
package net.sulin.test.rmi;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Server {
public static void main(String[] args) throws Exception {
bind();
}
public static Registry createRegistry() throws Exception {
Registry registry = null;
final int port = 2222;
registry = LocateRegistry.createRegistry(port);
return registry;
}
public static void bind() throws Exception{
Registry registry = null;
registry = createRegistry();
Upper upp = new UpperImpl();
registry.bind("upper", upp);
System.out.println("My RMI Bind Successfully");
}
}
|
以上部分是单一的 Client-Server
的远程方法调用
还有一对多的Client(one)-Server(many)
的远程方法调用,即服务器端有多个,不但可以分散请求压力,还可以防止服务器出现故障导致的一系列问题
还有一种Client/Server
的远程方法调用,即一个网络点即可以是
Client
也可以是
Server
。
还有服务器链的远程方法调用,即Client-Server-Server......
。
Client
请求的第一个
Server
不能完成全部工作,就可以设置服务器链,利用多个
Server
同步响应一个调用请求
后面这几种都是基于上面的单一远程方法调用。很容易理解的
下来看到第三章CORBA
了
、 本来是看网络通信底层的,怎么书上讲到分布式开发上了。。。
分享到:
相关推荐
RMI简单实例RMI简单实例RMI简单实例
java rmi java rmijava rmi javajava rmi java rmi rmi
完整的Rmi调用示例,极难得的Rmi应用示例
rmi的详细例子,rmi的详细用法,一看就懂
RMI 规范 RMI 详细介绍 共10章
分布式实验报告 RMI.docx 本实验报告主要介绍了 Java RMI(Remote Method Invocation,远程方法调用)的基本概念和实现步骤。RMI 是一种分布式对象通讯机制,允许运行在一个 Java 虚拟机的对象调用运行在另一个 ...
RMI教程 Java RMIRMI教程 Java RMIRMI教程 Java RMIRMI教程 Java RMIRMI教程 Java RMI
rmi小程序,RMI文档,为RMI初学者使用
RMI远程方法调用RMI远程方法调用RMI远程方法调用RMI远程方法调用RMI远程方法调用
1. Unpack RMI.rar and put the package "features" and "plugins" under the package "net.genady.rmi_2.0.2.1" to <%eclipse%> directory; 2. Copy rmi.jar and lic.jar under the package "crack" to ...
Spring-RMI (RMI调用, HTTP调用) 本人测试过了
本项目使用socket直接发送数据包来攻击rmi,通过反序列化攻击rmi,双击直接运行,对1099端口的rmi服务直接进行漏洞检测。
Weblogic Server与RMI RMI的使用介绍
java rmi上传文件 在这次的项目中,对于客户端与服务器之间的通信,想了许多办法,由于做的是富客户端应用,最终将技术选定在了RMI和Java-sockets两种之间,其中RMI的灵活性不高,客户端和服务器端都必须是java编写...
java RMI
spring RMI 简单例子
Java RMI 完整版 Java Remote Method Invocation(RMI)是一种分布式对象技术,允许使用 Java 编写分布式对象,不同的 Java 虚拟机(JVM)之间进行对象间的通讯。这使得应用程序(Application)可以远程调用方法,...
Java编程rmi实例,给出远程方法调用技术在java方面的具体例子。
web服务器 RMI meeting sokect
Java中RMI的实现机制Java中RMI的实现机制Java中RMI的实现机制Java中RMI的实现机制