网络编程
一、网络交互之RMI
1.RMI实现java非web项目之间数据信息的网络交互
搭建一个RMI服务的过程分为以下7步:
1.创建远程方法接口,该接口必须继承自Remote接口
2.创建远程方法接口实现类:
3.利用java自带rmic工具生成sutb存根类
(C:\Program Files\Java\jdk1.8.0_91\bin/rmic):
自动执行的,不需要你管
4.启动RMI注册服务(jdk1.5.0_15/bin/rmiregistry): 人工创建
rmiregistry服务,需要在代码中添加:LocateRegistry.createRegistry(1099))
5.编写服务端代码:ServerTest
6.运行服务端: ServerTest,且需要重新fix step
7.编写客户端代码并运行: ClientTest
服务端:
package com.rj.bd.rmis;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* @desc 服务端接口
* @author HYZ
* @time 2021年1月21日
*/
public interface IMyServer extends Remote{
public int add(int a,int b) throws RemoteException;
public int mul(int a,int b) throws RemoteException;
}
package com.rj.bd.rmis;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
/**
* @desc 服务端接口的实现类
* @author HYZ
* @time 2021年1月21日
*/
@SuppressWarnings("serial")
public class MyServerImpl extends UnicastRemoteObject
implements IMyServer {
protected MyServerImpl() throws RemoteException {
super();
}
@Override
public int add(int a, int b) throws RemoteException {
System.out.println(a+"+"+b+"="+(a+b));
return a+b;
}
@Override
public int mul(int a, int b) throws RemoteException {
System.out.println(a+"+"+b+"="+(a*b));
return a*b;
}
}
package com.rj.bd.rmis;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
/**
* @desc 服务端的测试类
* @author HYZ
* @time 2021年1月21日
*/
public class ServerTest {
//声明一个Registry对象,目的是为了将来能把服务
//端实现类的实例化对象注册到该上面
public static Registry registry=null;
public static void main(String[] args)
throws RemoteException, AlreadyBoundException {
//1.服务端的实现类进行实例化
MyServerImpl server = new MyServerImpl();
//2.将服务端注册到registry
getInstance().bind("server", server);
}
/**
* @desc Registry对象的实例化
* @return
* @throws RemoteException
*/
public static Registry getInstance() throws RemoteException{
return registry==null?(LocateRegistry.createRegistry(1099)):registry;
}
}
客户端:
package com.rj.bd.rmis;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
/**
* @desc RMI的客户端
* @author HYZ
* @time 2021年1月21日
*/
public class ClientTest {
public static void main(String[] args) throws RemoteException, NotBoundException {
//1.获取registry对象
Registry registry = LocateRegistry.getRegistry("127.0.0.1", 1099);
//2.在registry上寻找名字为server的对象
IMyServer server = (IMyServer) registry.lookup("server");
//调用方法
System.out.println(server.add(3, 6));
System.out.println(server.mul(2, 8));
}
}
2、Spring框架对RMI的封装和支持
SpringRMI
RmiServiceExporter:服务端暴露其接口
把任何Spring管理的Bean输出成一个RMI服务。通过把Bean包装在一个适配器类中工作。
适配器类被绑定到RMI注册表中,并且将请求代理给服务类。
RmiProxyFactoryBean:客户端通过通过JRMP访问服务,大白话意思就是:如果调用者要想调
用则可以通过RMIProxyFactoryBean这个代理工厂处理类来实现调用获取远程服务接口中的方法,
JRMP:java remote method protocol,Java特有的,基于流的协议
小结:
在服务器端使用org.springframework.remoting.rmi.RmiServiceExporter类来
注册服务;
在客户端使用org.springframework.remoting.rmi.RmiProxyFactoryBean来实
现远程服务的代理功能
ps: ***Spring框架是支持RMI技术的
3、RMI与socket的区别
RMI技术比较socket的网络编程主要有以下几个方面:
1.RMI是面向对象的,而后者不是。
2.RMI是与语言相绑定的。比如当你使用Java RMI技术的时候,客户端与服务器端
都必须使用Java开发。而socket的网络编程是使用独立于开发语言的,甚至独立于平台。
基于socket的网络编程,客户端与服务器端可以使用不同开发语言和不同的平台。
3.从网络协议栈的观点来看,RMI与socket的网络编程处于不同层次上。基于socket
的网络编程位于TCP协议,而RMI是基于TCP协议又定义了自己的应用协议,其传输层采用的
是Java远程方法协议(JRMP)。可见,在网络协议栈上,基于RMI的应用位置更高一些,这也
决定了,与socket的网络编程相比,RMI会丧失一些灵活性和可控性,但是好处是它带给了
应用开发者更多的简洁,方便和易用。比如:如果你用的是RMI,你不需要关心消息是怎么序
列化的,你只需要像本地方法调用一样,使用RMI。代价是:应用开发者无法很好地控制消息
的序列化机制。
4.两种方法的性能比较,其往往决定着你将使用那种技术来开发你的应用。
实验的结果是: RMI与TCP based socket相比,传输相同的有效数据,RMI需要占用
更多的网络带宽(protocol overhead)。从这里,我们可以得出一个一般性的结论:RMI
主要是用于远程方法的”调用“(RMI是多么的名符其实:)),其技术内涵强调的是 “调用”,
基于此,我能想到的是:移动计算,和远程控制,当你的应用不需要在client与server之间
传输大量的数据时,RMI是较好的选择,它简洁、易于开发。但是,一旦你的应用需要在client
与server之间传输大量的数据,极端的,比如FTP应用,则RMI是不适合的,我们应该使用 socket。
PS:
RMI的效率还是很高的,一般情况下会比Hessian更高效,比Web Service更是高效很多;
当然和socket这种东东相比,当然要低效一点了,socket更底层一些啊。RMI的具体实现,依
然是依赖于底层的Socket编程。
4、RMI与RPC的区别
RPC(Remote Procedure Call Protocol)远程过程调用协议,
通过网络从远程计算机上请求调用某种服务
RMI:远程方法调用(Remote Method Invocation)。能够让在客户端Java虚拟机
上的对象像调用本地对象一样调用服务端java 虚拟机中的对象上的方法
1.RPC与RMI区别
(1)RPC 跨语言,而 RMI只支持Java。
(2)RMI 调用远程对象方法,允许方法返回 Java 对象以及基本数据类型,而RPC
不支持对象的概念,传送到 RPC 服务的消息由外部数据表示
(External Data Representation, XDR) 语言表示,这种语言抽象了字节序类
和数据类型结构之间的差异。只有由XDR定义的数据类型才能被传递,可以说RMI是面
向对象方式的 Java RPC 。
(3)在方法调用上,RMI中,远程接口使每个远程方法都具有方法签名。如果一个方法
在服务器上执行,但是没有相匹配的签名被添加到这个远程接口上,那么这个新方法就
不能被RMI客户方所调用。
在RPC中,当一个请求到达RPC服务器时,这个请求就包含了一个参数集和一个文
本值,通常形成“classname.methodname”的形式。这就向RPC服务器表明,被请求
的方法在为 “classname”的类中,名叫“methodname”。然后RPC服务器就去搜索与
之相匹配的类和方法,并把它作为那种方法参数类型的输入。这里的参数类型是与RPC请
求中的类型是匹配的。一旦匹配成功,这个方法就被调用了,其结果被编码后返回客户方
5、RMI与WebService的区别
区别在于webservice主要是可以跨语言实现项目间的方法调用,
而rmi只是java内部语言进行的远程方法调用