- 论坛徽章:
- 0
|
Corba 部署服务器客户端例子
1 名词解释:
CORBA(公用对象请求代理体系)是基于对象技术的分布计算应用软件体系结构
OMG(对象管理组织)
IDL(Interface Definition Language,接口定义语言)
ORB(Object Request Broker,对象请求代理)
2 标准说明
CORBA标准主要分为三个部分:
接口定义语言(IDL)、对象请求代理(ORB),以及ORB之间的互操作协议IIOP,核心是对象请求代理。
CORBA可以抽象系统平台、网络通讯及编程语言的差异。
通过在CORBA技术规范中定义多种类型的服务,
名字服务(Naming Service)、
事务服务(Transaction Service)、
对象生命期服务(LifeCycle Service)、
并发控制服务(Concurrency Control Service)、
时间服务(Time Service)等功能,
CORBA为应用软件开发者提供一个全面、健壮、可扩展的分布对象计算平台.
使面向对象的应用软件在分布异构环境下方便地实现可重用、易移植和互操作。
3 和RMI技术比对
CORBA 不属于Java 平台本身。CORBA 对平台和语言无关,CORBA对象可以运行于任何平台之上。
用任何语言(包括 Java、C、C++和Smalltalk 等)编写,只要该语言具有IDL的映射。
CORBA 是为更大、可伸缩更强的系统准备的,在这些系统中可能有数千个对象;
CORBA 的编程和部署比RMI 更复杂,但允程序员开发需要事务、安全性等支持的企业级系统;
CORBA 的命名服务也比RMI 命名注册功能更强大和灵活。
CORBA 的实现称为ORB(Object Request Broker,对象请求代理)。
Java IDL 即是CORBA 的一个实现,它是JDK1.3 或更高版本的核心软件包之一,定义在org.omg.CORBA及其子包中。
在Java IDL 的支持下,开发人员可以使用如下两种方法将Java 和CORBA 集成在一起:
创建Java 对象并使之可在CORBA ORB 中展开,
创建Java 类并作为和其它ORB 一起展开的CORBA 对象的客户。
4 采用Java创建CORBA应用
CORBA对象服务的实现方式分为两种:对象的命名引用方式和字符串化对象引用方式。
不论采用何种高级语言,创建CORBA应用程序的过程大体如下:
● 编写IDL接口定义文件;
● 将接口定义文件编译为相应高级语言源代码,产生服务器框架与客户端存根;
● 基于服务器框架,编写服务对象实现程序;
● 基于客户端存根,编写客户对象调用程序;
● 分别编译客户对象和服务对象程序;
● 运行服务对象和客户对象程序;
5 CORBA实例分析
1. 接口定义 (main.idl)
module corba{
struct CmdPdu{
long session;
long age;
string name;
double salary;
};
typedef sequence<CmdPdu>; CmdPduArray;
interface IAgent{
CmdPdu getByName(in string name);
CmdPduArray getByAge(in long age);
long sendCmdPdu(in CmdPdu pdu,out CmdPdu wait,in boolean response);
};
};
说明:
module 后面的corba是模块名称,对应到Java上,表现为包路径
struct 是自定义结构,为了表现例子的通用性,自定义一个用于网络传输数据的对象。
typedef sequence 定义数组
long 数据类型. 常用类型有:long, string,double
接口:这里做了三个接口:
a 以 string 字符串作为入参,以CmdPdu作为出参
b 以 long 长整数(32bit) 作为入参,以CmdPdu数组作为出参
c 以 CmdPdu作为入参,同时有一个出参.response标志指出是否用出参带回返回值. 函数返回值是长整型结果.
更详细请参见http://www.jacorb.org/
2 编译存根和框架
idlj -fall Hello.idl
会看到产生如下一系列文件:
CmdPdu.java // 数据对象
CmdPduHelper.java // CmdPdu远程管理对象,可以控制CmdPdu对象的包装和传输
CmdPduHolder.java // CmdPdu回参携带者.可以用这个类的.value传递需要携带返回值的参数。
CmdPduArrayHolder.java // CmdPdu数组远程管理对象,可以控制一批CmdPdu对象的包装和传输
CmdPduArrayHelper.java // CmdPdu数组回参携带者.可以传送一批需要返回的CmdPdu参数。
IAgentOperations.java // 接口。包含我们定义的三个接口。
IAgent.java // 抽象接口,是融合IAgentOperations,IDLEntity的接口。系统中就用这个。
IAgentHolder.java // IAgent 远程管理对象,可以控制 IAgent 对象的包装和传输
IAgentHelper.java // IAgent 回参携带者.可以用这个类的.IAgent 传递需要携带返回值的参数。
IAgentPOA.java // 服务器端接口调用代理,把接口中的方法封装起来。适合Corba的统一调用接口。
_IAgentStub.java // 客户端接口调用代理,把接口中的方法封装起来。适合Corba的统一调用接口。
3 生成客户端使用代码
package com.client;
import org.omg.CORBA.ORB;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContext;
import org.omg.CosNaming.NamingContextHelper;
import corba.CmdPdu;
import corba.CmdPduHolder;
import corba.IAgent;
import corba.IAgentHelper;
public class LudClient {
public static void main(String args[]) {
try {
String[] initParam = new String[]{
"-ORBInitialPort","1055","-ORBInitialHost","192.168.110.213"
};
/* 创建和初始化 ORB */
ORB orb = ORB.init(initParam, null);
/* 获取根命名上下文 */
org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService" ;
NamingContext ncRef = NamingContextHelper.narrow(objRef);
/* 解析命名中的对象引用 */
NameComponent nc = new NameComponent("Hello", "" ;
NameComponent path[] = { nc };
IAgent h = IAgentHelper.narrow(ncRef.resolve(path));
/* 调用 Hello 服务器对象并打印结果 */
System.out.println("我在客户端,开始调用CORBA服务器端的'getByName'方法" ;
System.out.println("欢迎, " + h.getByName("javamxj blog" );
System.out.println("我在客户端,开始调用CORBA服务器端的'getByAge'方法" ;
System.out.println("欢迎, " + h.getByAge(1).length);
System.out.println("我在客户端,开始调用CORBA服务器端的'getByName'方法" ;
CmdPdu pdu = new CmdPdu();
CmdPduHolder hdPdu = new CmdPduHolder(new CmdPdu());
System.out.println("欢迎, " + h.sendCmdPdu(pdu,hdPdu,true));
System.out.println("返回1:"+hdPdu.value);
hdPdu = new CmdPduHolder(new CmdPdu());
System.out.println("欢迎, " + h.sendCmdPdu(pdu,hdPdu,false));
System.out.println("返回2:"+hdPdu.value);
} catch (Exception e) {
System.out.println("错误 : " + e);
e.printStackTrace(System.out);
}
}
}
4 创建服务端使用代理
/**
* 服务器端方法,用简单的输出替代复杂业务逻辑.
*/
package com.server;
import org.omg.CORBA.ORB;
import corba.CmdPdu;
import corba.IAgentPOA;
public class ServerImpl extends IAgentPOA {
private ORB orb;
public void setORB(ORB orb_val) {
orb = orb_val;
}
public ServerImpl() {
super();
}
public corba.CmdPdu getByName(String name) {
System.out.println("我在CORBA的服务器端,客户端正在调用'getByName'方法。 " ;
CmdPdu pdu = new CmdPdu();
pdu.name = "<S:" + name + ">;";
pdu.age = (int) System.currentTimeMillis() % 100;
return pdu;
}
public corba.CmdPdu[] getByAge(int age) {
System.out.println("我在CORBA的服务器端,客户端正在调用'getByAge'方法。 " ;
CmdPdu[] arr = new CmdPdu[3];
for (int i = 0; i < arr.length; i++) {
arr = new CmdPdu();
arr.age = age;
arr.name = "name_" + System.currentTimeMillis() % 100;
}
return arr;
}
public int sendCmdPdu(corba.CmdPdu pdu, corba.CmdPduHolder _wait,
boolean response) {
System.out.println("我在CORBA的服务器端,客户端正在调用'sendCmdPdu'方法: " + pdu);
int result = 1;
CmdPdu ret = new CmdPdu();
ret.age = pdu.age + 100;
ret.name = pdu.name + "100";
_wait.value = ret;
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
}
if (response) {
System.out.println("我在CORBA的服务器端,'sendCmdPdu'准备好回包返回: "
+ _wait.value);
result = 2500;
} else {
result = 3;
System.out.println("我在CORBA的服务器端,'sendCmdPdu' 不必回包返回: " + result);
}
return result;
}
}
5 创建服务器启动类
/**
* 启动服务类
*
* 启动服务以后,等待客户端的远程连接调用。
*/
package com.server;
import org.omg.CORBA.ORB;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;
import corba.IAgent;
import corba.IAgentHelper;
public class LudServer {
public static void main(String args[]) {
try {
String[] initParam = new String[]{
"-ORBInitialPort","1055","-ORBInitialHost","192.168.110.213"
};
// 创建和初始化 ORB
ORB orb = ORB.init(initParam, null);
// 获取对RootPOA的引用,启动POAManager
POA rootpoa = POAHelper.narrow(orb
.resolve_initial_references("RootPOA" );
rootpoa.the_POAManager().activate();
// 创建一个实例并将其向 ORB 注册
ServerImpl h = new ServerImpl();
h.setORB(orb);
System.out.println("将实例注册到ORB " ;
// 获取对服务端的对象引用
org.omg.CORBA.Object ref = rootpoa.servant_to_reference(h);
IAgent href = IAgentHelper.narrow(ref);
// 从名称服务中获取根元素名称上下文
org.omg.CORBA.Object objRef = orb
.resolve_initial_references("NameService");
NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
// 在Hello名称下注册新对象
String name = "Hello";
NameComponent path[] = ncRef.to_name(name);
ncRef.rebind(path, href);
// 等待客户端的调用.
orb.run();
System.out.println("等待CORBA客户端调用...");
}
catch (Exception e) {
System.err.println("ERROR: " + e);
e.printStackTrace(System.out);
}
System.out.println("HelloServer Exiting ...");
}
}
6 执行测试(顺序不能错)
// 启动那么service 注意端口要和server 和 client的一致。
tnameserv -ORBInitialPort 1055
// 启动服务器
java com.server.LudServer
// 启动客户端
java com.client.LudClient |
|