JDK文档阅读之Using Custom Socket Factories with Java RMI
来源:互联网 发布:济南网络推广 编辑:程序博客网 时间:2024/06/06 00:01
1.自定义的Socket工厂可以用来做什么?
控制远程方法调用在网络级别的通信方式。例如:
- 设置Socket选项
- 控制地址绑定
- 控制连接的建立(例如要求身份验证)
- 控制数据编码(例如添加加密和压缩)
客户端socket工厂:
- 控制产生sockets,用来初始化远程调用。
- 控制连接如何建立,使用哪种类型的socket。
服务器端socket工厂:
- 控制生成服务器端sockets,用来接收远程调用
- 控制传入的连接是如何被监听和接受的,以及用于输入连接socket的类型。
2.建立自定义的Socket工厂
- 实现自定义ServerSocket和Socket
在JDK8文档实例中,自定义socket工厂创建sockets,使用了XOR加密和解密技术。而这种技术可以被知识渊博的密码分析员解密,JDK8文档使用仅仅是为了Demo的简单性。XOR sockets 使用特别的输入输出流实现来处理从socket中写入和输出数据。
(具体的代码请自行下载jdk8文档查阅)
class XorSocket extends Socket {}class XorInputStream extends FilterInputStream {}class XorOutputStream extends FilterOutputStream {}class XorServerSocket extends ServerSocket {}
- 实现自定义RMIClientSocketFactory
客户端socket工厂,XorClientSocketFactory- 实现了java.rmi.server.RMIClientSocketFactory接口,需要实现createSocket方法以用来返回适当的客户端socket实例,一个XorSocket。
- 实现java.io.Serializable接口以实现实例可以序列化客户端作为远程存根(存根就相当于一个代理)的一部分。实现equals和hashcode方法可以正确地在等价的客户端socket工厂的远程存根实例之间分享资源。
import java.io.IOException;import java.io.Serializable;import java.net.Socket;import java.rmi.server.RMIClientSocketFactory;/** * @author liuffei * @date 2017年9月18日 * @description */public class XorClientSocketFactory implements RMIClientSocketFactory, Serializable { private byte pattern; public XorClientSocketFactory(byte pattern){ this.pattern = pattern; } @Override public Socket createSocket(String host, int port) throws IOException { return new XorSocket(host,port,pattern); } public int hashCode(){ return pattern; } public boolean equals(Object obj){ return (getClass() == obj.getClass() && pattern == ((XorClientSocketFactory)obj).pattern); }}
- 实现自定义RMIServerSocketFactory
服务器端socket工厂,XorServerSocketFactory,实现了java.rmi.server.RMIServerSocketFactory接口。服务器端socket工厂需要实现createServerSocket方法来返回适当的服务器socket实例,一个XorServerSocket。- 服务器端socket工厂不需要实现Serializable接口,因为服务器socket工厂实例没有包含在远程存根中。
- 同样需要实现equals和hashcode方法,JAVA RMI 实现可以正确地在等价的socket工厂导出的远程对象之间分享资源。
import java.io.IOException;import java.net.ServerSocket;import java.rmi.server.RMIServerSocketFactory;public class XorServerSocketFactory implements RMIServerSocketFactory { private byte pattern; public XorServerSocketFactory(byte pattern){ this.pattern = pattern; } @Override public ServerSocket createServerSocket(int port) throws IOException { return new XorServerSocket(port,pattern); } public int hashCode(){ return pattern; } public boolean equals(Object obj){ return (getClass() == obj.getClass() && pattern == ((XorServerSocketFactory)obj).pattern); }}
3.在应用中使用自定义的Socket工厂
两个步骤:
- 服务器应用:创建远程对象并且导出。存储一个远程对象存根的引用在Java RMI注册表,这样客户端才能查找到它。
- 查找远程对象存根和调用远程方法。客户端应用不需要引用自定义socket工厂。客户端为远程对象寻找存根时,客户端socket工厂将会被下载到客户端。
第一步:服务器应用
如果远程对象通信要求使用自定义的sockets,需要指定当你导出远程对象时使用哪一个自定义socket工厂。当你的应用导出指定的自定义socket工厂,Java RMI运行时会使用相应的自定义RMIServerSocketFactory来创建服务器socket,以接受远程对象的远程调用,并且会创建一个相应的自定义RMIClientSocketFactory存根。当使用存根对远程对象进行远程调用时,将使用客户端socket工厂创建连接。
import java.rmi.Remote;import java.rmi.RemoteException;public interface Hello extends Remote{ String sayHello() throws RemoteException;}
import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;import java.rmi.server.RMIClientSocketFactory;import java.rmi.server.RMIServerSocketFactory;import java.rmi.server.UnicastRemoteObject;public class HelloImpl implements Hello { public HelloImpl(){} public String sayHello(){ return "Hello World!!!"; } public static void main(String args[]){ if(System.getSecurityManager() == null){ System.setSecurityManager(new SecurityManager()); } byte pattern = (byte)0xAC; try{ HelloImpl obj = new HelloImpl(); RMIClientSocketFactory csf = new XorClientSocketFactory(pattern); RMIServerSocketFactory ssf = new XorServerSocketFactory(pattern); Hello stub = (Hello) UnicastRemoteObject.exportObject(obj,0,csf,ssf); LocateRegistry.createRegistry(2002); Registry registry = LocateRegistry.getRegistry(2002); registry.rebind("Hello",stub); System.out.println("HelloImpl bound in registry"); }catch(Exception e){ System.out.println("HelloImpl exception:"+e.getMessage()); e.printStackTrace(); } }}
Server应用创建的远程对象实现了远程接口Hello,并且使用自定义的socket工厂导出对象,使用java.rmi.server.UnicastRemoteObject的exportObject方法,自定义的socket工厂作为参数。接着,创建本地注册表,在注册表里,为一个名称为Hello的远程对象的存根绑定引用。
第二步:客户端应用
import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;public class HelloClient { public static void main(String args[]){ if(System.getSecurityManager() == null){ System.setSecurityManager(new SecurityManager()); } try{ Registry registry = LocateRegistry.getRegistry(2002); Hello obj = (Hello) registry.lookup("Hello"); String message = obj.sayHello(); System.out.println(message); }catch(Exception e){ System.out.println("HelloClient exception:"+e.getMessage()); e.printStackTrace(); } }}
客户端应用程序获得对服务器应用程序使用的注册表的引用。然后它查找远程对象的存根并调用它的远程方法sayHello。
4.编译和运行应用
第一步:编译远程接口,服务端文件和客户端文件
javac *.java
第二步:运行服务器
将class文件所在目录添加到classpath中,进入到class文件的根目录。
执行start java HelloImpl 如果执行成功会返回HelloImpl bound in registry
我的项目路径和执行过程如下:
如果执行过程抛出一个java.security.AccessControlException:access denied,需要添加一个安全策略文件:
我这里的文件名是MyPolicy.policy 位置在D盘下
文本格式如下:
grant { permission java.net.SocketPermission "localhost:*","connect,resolve,accept";};
start java -Djava.security.policy=D:/文件路径 HelloImpl
关于这个安全策略有很多解决方案,这篇文章总结得很好:
RMI总结及可能产生的几种异常及解决
第三步: 运行客户端
start java -Djava.security.policy=D:/文件路径 HelloClient
返回结果:Hello,World!!!
- JDK文档阅读之Using Custom Socket Factories with Java RMI
- JDK文档阅读之RMI(远程方法调用)
- Using RMI with SSL
- Java JDK API文档-------Socket
- java rmi和socket之比较
- Java RMI之HelloWorld RMI
- Jdk源码阅读之Java.util.concurrent
- Java RMI和socket比较
- Java RMI VS TCP Socket
- jdk8文档阅读之java.io
- Using Custom Java code in ODI
- Part 3 - Using custom view engines with asp.net mvc
- Using the java.rmi.server.codebase Property
- Configuring Java (J9) on a Pocket PC with RMI and SWT using CDC Personal Profile: some experiences and issues
- Configuring Java (J9) on a Pocket PC with RMI and SWT using CDC Personal Profile: some experiences and issues
- Java RMI之HelloWorld
- Java RMI之介绍
- Java RMI之HelloWorld
- Android手机开发之动画二三事
- 杂谈
- Run Tomcat时出现A java Exception has occurred的错误及MyEclipse添加Tomcat服务器
- 链表中倒数第K个结点
- 学生信息管理系统错误总结
- JDK文档阅读之Using Custom Socket Factories with Java RMI
- oj 单身情歌
- 译:java
- POJ 3299.Humidex
- 与癌症斗争的乔布斯
- 机器学习一(逻辑回归)
- hdu 1878 欧拉回路
- Spring MVC框架原理(待补充)
- pycharm 提示 No module named 'XXX'