运用JAVA技术实现分布式计算
目前,运用JAVA技术实现分布式计算的技术主要有RMI、CORBA以及Scoket通信三方面技术,下面就这三方面技术分别做一下比较。
l RMI
RMI技术远程调用,是基于RPC技术发展而来的。其开发过程基本由下面几个过程
1. 定义远程接口
2. 实现远程接口
3. 编写使用远程对象
4. 生成stub(客户代理)以及skeletom(服务器实体)
5. 启动注册表并且注册对象
6. 运行服务器和客户
下面就分别对其简单介绍
1. 定义远程接口
package shi.rmi;
public interface RemoteShiInterface extends java.rmi.Remote
{
String message(String message)throws java.rmi.RemoteException;
}
接口必须继承于java.rmi.Remote;并且定义方法
必须抛出java.rmi.RemoteExcetption的异常。
2. 实现远程接口
package shi.rmi;
import java.rmi.Naming;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
public class RemoteObject extends UnicastRemoteObject implements RemoteShiInterface
{
String name;
public RemoteObject(String name)throws RemoteException
{
super();
this.name=name;
}
public String message(String message)throws RemoteException
{
String returnString="My Name is :"+name+",thank for your message:"+message;
System.out.println("Returning:"+returnString);
System.out.println("hello stonewall");
return "My Name is:"+name+",thanks for your message:"+message+"stonewall";
}
public static void main(String args[])
{
//System.setSecurityManager(new RMISecurityManager());
try
{
String myName="RMI";
RemoteObject theServer=new RemoteObject(myName);
Naming.rebind("//192.168.1.169:1099/RMI",theServer);
System.out.println("Ready to continue");
}catch(Exception e)
{
System.out.println("An Exception occured while creating server");
System.out.println(e);
}
}
}
必须注意的就是运用红笔标记出来的代码。基本上就是按照此种样式来编写的。另外,Naming rebind(“URL”,””)其中URL 必须制定,而且还要指定其访问端口如果不指定RMI默认端口是1099。
3. 编写使用远程对象
package shi.rmi;
import java.rmi.RMISecurityManager;
import java.rmi.Naming;
public class RemoteClient
{
public static void main(String args[])
{
//System.setSecurityManager(new RMISecurityManager());
try
{
RemoteShiInterface server=(RemoteShiInterface)Naming.lookup("//192.168.1.169:1099/RMI");
String serverString=server.message("Hello There");
System.out.println("The server says:/n"+serverString);
}catch(Exception e)
{
System.out.println(e);
}
}
}
System.setSecurityManager(new RMISecurityManager()) 安全管理的代码,如果把它注释掉,那么需要建立一个安全策略文件,比如文件名 policy.txt
Grant {
permission java.security.AllPermission “”,””;
};
运行程序形式如下:
D:/RMISample/server>java -Djava.security.policy=policy.txt RemoteObject
D:/RMISample/client>java -Djava.security.policy=policy.txt RemoteClient
如果注释就可以直接运行:
Java RemoteObject java RemoteClient
4. 生成stub(客户代理)以及skeletom(服务器实体)
rmic RemoteObject
5. 启动注册表并且注册对象
start rmiregistry 1099
6. 运行服务器和客户
java RemoteObject
java RemoteClient
l Socket
Socket编程相对来说就比较简单,服务器端利用ServerSocket的accept()方法来倾听客户端发出的请求。如果,希望客户端倾听网络中多台机器发出的请求,那么可以将Socket放到一个Thread中去。下面分别列出服务器端和客户端代码。
服务器端代码:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Server.java
package shi.socket;
import java.io.*;
import java.net.*;
public class Server extends ServerSocket
{
private static final int SERVER_PORT = 10000;
public Server() throws IOException
{
super(SERVER_PORT);
try{
while (true){
Socket socket = accept();
new CreateServerThread(socket);
}
}catch (IOException e){
e.printStackTrace();
}
finally{
close();
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CreateServerThread.java
package shi.socket;
import java.net.*;
import java.io.*;
public class CreateServerThread extends Thread
{
private Socket client;
private BufferedReader in;
private PrintWriter out;
private static InetAddress serverAddr;
public CreateServerThread(Socket s) throws IOException{client = s;
in=new BufferedReader(new InputStreamReader(client.getInputStream(), "GB2312"));
out = new PrintWriter(client.getOutputStream(), true);
out.println("--- Welcome ---");
start();
}
public void run(){
try {
serverAddr = InetAddress.getByName(null);
while (true) {
String str = in.readLine();
if (str.equals("bye")) break;
System.out.println("Echoing: " + str);
out.println(serverAddr + " : " + str);
}
out.println("---Good Bye---");
System.out.println("closing...");
} catch (IOException e) {
} finally {
try {
client.close();
} catch(IOException e) {e.printStackTrace();}
}
}
public static void main(String args[]) throws IOException{
serverAddr = InetAddress.getByName(null);
System.err.println(serverAddr.toString() +"--"+ "Create server Thread...");
new Server();
}
}
客户端代码:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Client.java
package shi.socket;
import java.io.*;
import java.net.*;
public class Client
{
Socket socket;
BufferedReader in;
PrintWriter out;
public Client()
{
try
{
InetAddress addr =
InetAddress.getByName("192.168.1.169");
socket = new Socket(addr, 10000);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(),true);
System.err.println(addr.toString() +"--"+ "Create Client Thread...");
System.out.println(in.readLine());
for (int i=0;i<10;i++){
String str = addr.toString() + " : " + "The ";
out.println(str + i);
System.out.println(in.readLine());
}
out.println("bye");
System.out.println(in.readLine());
}catch(Exception e){
e.printStackTrace();
}finally{
System.out.println("closing...");
try {
in.close();
} catch (IOException e1) {
e1.printStackTrace();
}
out.close();
try {
socket.close();
} catch (IOException e2) {
e2.printStackTrace();
}
}
}
public static void main(String[] args){
new Client();
}
}
l CORBA
CORBA也是一种分布式的解决方案。具体文档介绍请参考
http://www-128.ibm.com/developerworks/cn/java/exploring-corba/index.html
下面就主要代码贴出:
IDL编写的接口
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Hello.idl
module shi
{
module corba
{
interface Hello
{
string sayHello();
oneway void shutdown();
};
};
};
运用IDL-Java编译器编译
idlj -fall Hello.idl
会生成以下几个文件
_HelloStub.java stub类
Hello.java
HelloHelper.java
HelloHolder.java
HelloOperations.java
HelloPOA.java Skeleton类
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 接口实现类HelloImpl.java
class HelloImpl extends HelloPOA {
private ORB orb;
public void setORB(ORB orb_val) {
orb = orb_val;
}
// implement sayHello() method
public String sayHello() {
return "/nHello world !!/n";
}
// implement shutdown() method
public void shutdown() {
orb.shutdown(false);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 服务类HelloServer.java
import shi.corba.*;
import org.omg.CosNaming.*;
//import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
import org.omg.PortableServer.*;
import org.omg.PortableServer.POA;
//import java.util.Properties;
public class HelloServer {
public static void main(String args[]) {
try{
// create and initialize the ORB
ORB orb = ORB.init(args, null);
// get reference to rootpoa & activate the POAManager
POA rootpoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
rootpoa.the_POAManager().activate();
// create servant and register it with the ORB
HelloImpl helloImpl = new HelloImpl();
helloImpl.setORB(orb);
// get object reference from the servant
org.omg.CORBA.Object ref = rootpoa.servant_to_reference(helloImpl);
Hello href = HelloHelper.narrow(ref);
// get the root naming context
// NameService invokes the name service
org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
// Use NamingContextExt which is part of the Interoperable
// Naming Service (INS) specification.
NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
// bind the Object Reference in Naming
String name = "Hello";
NameComponent path[] = ncRef.to_name( name );
ncRef.rebind(path, href);
System.out.println("HelloServer ready and waiting ...");
// wait for invocations from clients
orb.run();
}
catch (Exception e) {
System.err.println("ERROR: " + e);
e.printStackTrace(System.out);
}
System.out.println("HelloServer Exiting ...");
}
}
客户端代码:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HelloClient.java
import shi.corba.*;
import org.omg.CosNaming.*;
//import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
public class HelloClient
{
static Hello helloImpl;
public static void main(String args[])
{
try{
// create and initialize the ORB
ORB orb = ORB.init(args, null);
// get the root naming context
org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
// Use NamingContextExt instead of NamingContext. This is
// part of the Interoperable naming Service.
NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
// resolve the Object Reference in Naming
String name = "Hello";
helloImpl = HelloHelper.narrow(ncRef.resolve_str(name));
System.out.println("Obtained a handle on server object: " + helloImpl);
System.out.println(helloImpl.sayHello());
helloImpl.shutdown();
} catch (Exception e) {
System.out.println("ERROR : " + e) ;
e.printStackTrace(System.out);
}
}
}
l 综述:
分析以上三种技术,我个人认为CORBA适合大的网络应用。Socket适合于网络间小数据量传输。RMI远程方法调用,不仅适合于网络间的小型应用,而且RMI的扩展要好于Socket通信。