编程实例:数组相加
本程序是一个数组相加程序:由客户端提供两个数组,然后服务器将它们相加并将结果返回给客户端。
数组相加:暂时服务
开发任何CORBA应用程序首先都要使用OMG的接口定义语言(IDL)定义接口。数组相加程序的IDL接口定义如下面代码所示。在这我们定义了一个名为ArithApp的模块(相当于Java中的包);一个名为Add的接口,包含了一个常量,一个新的数据类型array(定义成long类型的一个数组),还有addArrays操作,它将两个数组作为参数输入(用关键字in指定),另一个数组作为输出(用关键字out指定)。
代码示例1:Add.idl
module ArithApp {
interface Add {
const unsigned short SIZE=10;
typedef long array[SIZE];
void addArrays(in array a, in array b,
out array result);
};
};
现在你可以编译这个IDL接口生成Java程序,生成程序骨干和框架。这可以通过idlj编译器实现。当你编译时,你可以指定是只生成客户端框架还是服务端框架或者两者同时生成。在这你需要同时生成客户端和服务端框架。使用下面的命令:
prompt> idlj -fall Add.idl
编译将生成许多文件,你可以观察一下生成了哪些文件。你可以发现一个名为ArithApp的新子目录被创建了。这是由于OMG IDL中的模块就对应于Java中的包。
注意:J2SE1.4中的idlj编译器对服务器端生成的是轻便对象适配器(POA)。但你可以使用-oldImplBase参数编译使用J2SE1.3或更早版本编写的CORBA程序,从而生成与早期版本一致的文件。注意新版本程序就不再生成这些现在已不被提倡使用的服务器端映射了。
下一步就是要实现代码1中所定义的IDL接口。代码示例2就展示了这样的一个实现。AddImpl类是AddPOA的子类,AddPOA类是由idlj编译器从IDL接口生成的。注意addArrays函数的第三个参数。在这我们只是简单的使用了一个数组保持器,因为在前面我们已经使用了out参数指定了输出数组的类型。
代码示例2:AddImpl.java
import ArithApp.*;
import org.omg.CORBA.*;
class AddImpl extends AddPOA {
private ORB orb;
public AddImpl(ORB orb) {
this.orb = orb;
}
// implement the addArrays() method
public void addArrays(int a[], int b[],
ArithApp.AddPackage.arrayHolder result) {
result.value = new int[ArithApp.Add.SIZE];
for(int i=0; i<ArithApp.Add.SIZE; i++) {
result.value[i] = a[i] + b[i];
}
}
}
接着就要开发服务器端程序了。代码示例3中展示了一个示例程序。服务器要执行下列任务:
n 新建和初始化ORB。
n 为接口实现生成实例并在ORB上注册。
n 获取对RootPOA的引用,启动POAManager。
n 获取对服务端的对象引用。
n 从名称服务中获取根元素名称上下文,在Add名称下注册新对象。
n 等待客户端的调用。
代码示例3:AddServer.java
import ArithApp.*;
import org.omg.CORBA.*;
import org.omg.CosNaming.*;
import org.omg.PortableServer.*;
import org.omg.PortableServer.POA;
import org.omg.CosNaming.NamingContextPackage.*;
public class AddServer {
public static void main(String args[]) {
try{
// create and initialize the ORB
ORB orb = ORB.init(args, null);
// create an implementation and register it with the ORB
AddImpl impl = new AddImpl(orb);
// get reference to rootpoa & activate the POAManager
POA rootpoa = POAHelper.narrow(
orb.resolve_initial_references("RootPOA"));
rootpoa.the_POAManager().activate();
// get object reference from the servant
org.omg.CORBA.Object ref =
rootpoa.servant_to_reference(impl);
Add href = AddHelper.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 = "Add";
NameComponent path[] = ncRef.to_name( name );
ncRef.rebind(path, href);
System.out.println("AddServer
ready to add up your arrays ....");
// wait for invocations from clients
orb.run();
} catch (Exception e) {
System.err.println("ERROR: " + e);
e.printStackTrace(System.out);
}
System.out.println("AddServer Exiting ....");
}
}
现在要实现客户端。客户端的实现如代码示例4所示。客户端要执行下面的操作:
n 生成并初始化ORB。
n 获取对根元素名称上下文的引用。
n 在名称上下文中查找Add对象,获取对它的引用。
n 调用addArrays方法,输出结果。
代码示例4:AddClient.java
import ArithApp.*;
import org.omg.CORBA.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
public class AddClient {
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 = "Add";
Add impl = AddHelper.narrow(ncRef.resolve_str(name));
System.out.println("Handle obtained on server object: " + impl);
// the arrays to be added
int a[] = {3, 7, 6, 9, 2, 5, 0, 1, 4, 8};
int b[] = {8, 2, 1, 7, 4, 9, 3, 5, 0, 6};
// the result will be saved in this new array
ArithApp.AddPackage.arrayHolder c =
new ArithApp.AddPackage.arrayHolder();
// invoke the method addArrays()
impl.addArrays(a, b, c);
// print the new array
System.out.println("The sum of the two arrays is: ");
for(int i=0;i<ArithApp.Add.SIZE;i++) {
System.out.println(c.value[i]);
}
} catch (Exception e) {
System.out.println("ERROR : " + e) ;
e.printStackTrace(System.out);
}
}
}
现在可以编译AddImpl、AddServer、AddClient类,以及由idlj编译器生成的框架文件。可以使用如下的javac命令进行编译:
prompt> javac *.java ArithApp/*.java
运行该程序:
1.启动orbd名称服务。
prompt> orbd -ORBInitialPort 2500
2500是你想要orbd运行的端口号。要注意需要-ORBInitialPort作为命令行参数指定。
2.启动AddServer:
prompt> java AddServer -ORBInitialPort 2500
在本例中我们将AddServer与orbd运行在同一主机上。如果orbd服务运行在另一台主机上,那么就要使用-ORBInitialHost参数告知服务器到哪去寻找orbd服务。
3.启动AddClient:
prompt> java AddClient -ORBInitialPort 2500
我们可以看到数组相加的运行结果。