流程圖如下:
Hello.java:
public interface Hello extends java.rmi.Remote {
//因為是跨網調用,所有申請時一定要拋出異常
String sayHello() throws java.rmi.RemoteException;
}
HelloClient.java:
import java.rmi.*;
import java.rmi.registry.*;
public class HelloClient {
public static void main(String args[]) {
/*
* Create and install a security manager
*/
/*getSecurityManager:
* 取得系統安全接口,如果當前應用程序已經建立安全應用管理器,那么就返回該安全管理器
* 否則就返回null
*/
if (System.getSecurityManager() == null) {
System.setSecurityManager(new SecurityManager());
}
try {
/*getRegistry:
* Returns a reference to the the remote object <code>Registry</code> for
* the local host on the specified <code>port</code>.
*/
//打開一個注冊,端口號為2002
Registry registry = LocateRegistry.getRegistry(2002);
/*lookup:
* Returns the remote reference bound to the specified
* <code>name</code> in this registry.
*/
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();
}
}
}
HelloImpl.java:
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
{
/*
* Constructs a HelloImpl remote object.
*/
public HelloImpl()
{
}
/*
* Returns the string "Hello World!".
*/
public String sayHello()
{
return "Hello World!";
}
public static void main(String[] args)
{
/*
* Create and install a security manager
*/
if (System.getSecurityManager() == null)
{
System.setSecurityManager(new SecurityManager());
}
byte pattern = (byte) 0xAC;
try
{
/*
* Create remote object and export it to use
* custom socket factories.
*/
HelloImpl obj = new HelloImpl();
RMIClientSocketFactory csf = new XorClientSocketFactory(pattern);
RMIServerSocketFactory ssf = new XorServerSocketFactory(pattern);
/*
* 使用一個由socket factory指定的轉換導出遠程對象,使它可以接收遠程輸入調用
* 導出遠程對象使它能夠接收輸入調用,使用由所給的socket工廠指定的轉換
* public static Remote exportObject(Remote obj, int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
*/
Hello stub =
(Hello) UnicastRemoteObject.exportObject(obj, 0, csf, ssf);
/*
* Create a registry and bind stub in registry.
*/
//開啟服務端口
LocateRegistry.createRegistry(2002);
//獲得服務端口
Registry registry = LocateRegistry.getRegistry(2002);
//創建一個名為Hello的綁定服務
registry.rebind("Hello", stub);
System.out.println("HelloImpl bound in registry");
}
catch (Exception e)
{
System.out.println("HelloImpl exception: " + e.getMessage());
e.printStackTrace();
}
}
}
XorServerSocketFactory.java:
import java.io.*;
import java.net.*;
import java.rmi.server.*;
public class XorServerSocketFactory
implements RMIServerSocketFactory {
private final byte pattern;
public XorServerSocketFactory(byte pattern) {
this.pattern = pattern;
}
public ServerSocket createServerSocket(int port)
throws IOException
{
return new XorServerSocket(port, pattern);
}
/*
* 一定要引用hashCode()及equals(Object obj)方法,因為這樣JAVA RMI引用將會
* 正確的與使用相應的SOCKET工廠的遠程導出對象分享資源
*/
public int hashCode() {
return (int) pattern;
}
public boolean equals(Object obj) {
return (getClass() == obj.getClass() &&
pattern == ((XorServerSocketFactory) obj).pattern);
}
}
XorClientSocketFactory.java:
public class XorClientSocketFactory
implements RMIClientSocketFactory, Serializable {
private final byte pattern;
public XorClientSocketFactory(byte pattern) {
this.pattern = pattern;
}
public Socket createSocket(String host, int port)
throws IOException
{
return new XorSocket(host, port, pattern);
}
public int hashCode() {
return (int) pattern;
}
public boolean equals(Object obj) {
return (getClass() == obj.getClass() &&
pattern == ((XorClientSocketFactory) obj).pattern);
}
}
XorServerSocket.java:
import java.io.*;
import java.net.*;
class XorServerSocket extends ServerSocket {
/*
* The pattern used to "encrypt" and "decrypt" each byte sent
* or received by the socket.
*/
private final byte pattern;
/*
* Constructor for class XorServerSocket.
*/
public XorServerSocket(int port, byte pattern) throws IOException {
super(port);
this.pattern = pattern;
}
/*
* Creates a socket of type XorSocket and then calls
* implAccept to wait for a client connection.
*/
public Socket accept() throws IOException {
Socket s = new XorSocket(pattern);
//調用父類ServerSocket中的方法,也可以不加super
//implAccept():ServerSocket的子類使用這個方法override accept()方法,
//這樣可以返回他們自己的子類SOCKET
super.implAccept(s);
return s;
}
}
XorSocket.java:
import java.io.*;
import java.net.*;
class XorSocket extends Socket {
/*
* The pattern used to "encrypt" and "decrypt" each byte sent
* or received by the socket.
*/
private final byte pattern;
/* The InputStream used by the socket. */
private InputStream in = null;
/* The OutputStream used by the socket */
private OutputStream out = null;
/*
* Constructor for class XorSocket.
*/
public XorSocket(byte pattern)
throws IOException
{
//繼承Socket類的所有屬性
super();
this.pattern = pattern;
}
/*
* Constructor for class XorSocket.
*/
public XorSocket(String host, int port, byte pattern)
throws IOException
{
//調用父類的方法,生成一個由指定主機的指定端口的SOCKET
super(host, port);
//這個pattern就是由用戶指定的一個加密參數
this.pattern = pattern;
}
/*
* Returns a stream of type XorInputStream. 重寫父類的getInputStream()方法
*/
public synchronized InputStream getInputStream() throws IOException {
if (in == null) {
in = new XorInputStream(super.getInputStream(), pattern);
}
return in;
}
/*
*Returns a stream of type XorOutputStream. 重寫父類的getOutputStream()方法
*/
public synchronized OutputStream getOutputStream() throws IOException {
if (out == null) {
out = new XorOutputStream(super.getOutputStream(), pattern);
}
return out;
}
}
XorInputStream.java:
import java.io.*;
class XorInputStream extends FilterInputStream {
/*
* The byte being used to "decrypt" each byte of data.
*/
private final byte pattern;
/*
* Constructs an input stream that uses the specified pattern
* to "decrypt" each byte of data.
*/
public XorInputStream(InputStream in, byte pattern) {
super(in);
this.pattern = pattern;
}
/*
* Reads in a byte and xor's the byte with the pattern.
* Returns the byte.
*/
public int read() throws IOException {
//調用父類的讀方法
int b = in.read();
//If not end of file or an error, truncate b to one byte
if (b != -1)
//進行異或運算
b = (b ^ pattern) & 0xFF;
return b;
}
/*
* Reads up to len bytes
*/
public int read(byte b[], int off, int len) throws IOException {
//調用父類的讀方法
int numBytes = in.read(b, off, len);
if (numBytes <= 0)
return numBytes;
for(int i = 0; i < numBytes; i++) {
//對讀入的每個字節都進行異或運算
b[off + i] = (byte)((b[off + i] ^ pattern) & 0xFF);
}
return numBytes;
}
}
XorOutputStream.java:
import java.io.*;
class XorOutputStream extends FilterOutputStream {
/*
* The byte used to "encrypt" each byte of data.
*/
private final byte pattern;
/*
* Constructs an output stream that uses the specified pattern
* to "encrypt" each byte of data.
*/
public XorOutputStream(OutputStream out, byte pattern) {
super(out);
this.pattern = pattern;
}
/*
* XOR's the byte being written with the pattern
* and writes the result.
*/
public void write(int b) throws IOException {
out.write((b ^ pattern) & 0xFF);
}
}
還有一個安全策略文件傳不上來
自已弄一個
這里還是把運行步聚寫下來:
編譯及運行程序
第一步:
javac *.java
第二步:對引用類運行rmic命令
rmic HelloImpl
第三步:運行服務端
java -Djava.security.policy=policy HelloImpl
正確運行你會看到下面的顯示
HelloImpl bound in registry
第四步:運行客戶端
java -Djava.security.policy=policy HelloClient
正常運行你會看到如下輸出
Hello World!