您的位置:首页 > 编程语言 > C语言/C++

亲身体验CORBA: 使用java和C++混合编程

2010-08-27 11:59 344 查看
DL定义,ORB也可以完成相互的通信。

所有的文档在强调服务器及客户机可以是Java也可以是C++或其他语言(如:Delphi)进行编写,但在网站或书本是没有详细说如
何应对多语言客户机的例子。《JAVA2核心技术》上面有些说明,但也只是介绍性的文章,故自己下载了omniORB304,进行了一次使用SUN的
tnameserv命名服务程序,服务器用JAVA编写,客户机分别用JAVA和C++(VC6+omniORB)编写的试验,希望通过一次编程的具体操
作实例来体验或明了CORBA思想。

总体的编写过程如下:

用IDL定义一个接口文件,描绘要实现的功能,也可以说是定义一个要实现功能的一个模版(SysProp.idl)

使用"IDL to Java"编译器(这里是IDLJ)将IDL文件转化为Java编程语言中编写的接口定义,生成所需的代码存根及helper类

使用Java语言编写客户机和服务器的实现程序。

使用"IDL to C++"编译器(这里是omniidl)将IDL文件转化为C++编程语言中编写的接口定义,生成所需的代码存根及helper类

使用C++语言编写客户机实现程序(当然也可编写服务器程序,但本次试验没有进行)

起动命名服务tnameserv

起动Java编写的服务程序

用Java和C++编写的客户机分别调用相应的服务

 








回页首

运行环境的设定:

 

总体环境由jdk1.3+omniORB3.0(www.uk.research.att.com/omniORB/doc/3.0) +vc6 组成,下面说明具体的安装。

2.1. 安装JDK1.3

 

从SUN公司DOWN JDK1.3或者通过其他方式得到jdk1.3进行安装,再设定相应的环境变量,在本文测试用的电脑上是如下所示:

CLASSPATH=.;

JAVA_HOME=D:/jdk130

 

修改原来的PATH变量,添加"%JAVA_HOME%/bin;",如下

PTAH=%JAVA_HOME%/bin;原变量

 

注意:我在第一次使用jbuilder的jdk1.3时,服务器不能正常工作,我只是发觉这么一回事,具体原因与本文无关而没有进行了解,请谅。

2.2. 安装VC6

 

VC6按常规方式安装,注意的是:在本文测试用的电脑上安装在如下位置

C:/Program Files/Microsoft Visual Studio

2.3. 安装omniORB

 

从 www.uk.research.att.com/omniORB/doc/3.0 下载omniORB3.0 ( 本文测试所下载的文件是 omniORB_304_x86_win32.zip )。

用WINZIP进行解压omniORB_304_x86_win32.zip到omniORB_304_x86_win32目录,目录内存在omni目录,复制omni目录内的文件到你把想存放的位置。

测试电脑安装在
C:/omni

根据C:/omni/README.win32 文档进行设定,由于运行程序及命令行在控制台进行,所以本次测试并不根据文档要求去设定环境变量,而是编写了一个omni.bat,在使用控制台时,首先运行。

本测试电脑omni.bat内容如下

set TOP=c:/omni

set path=%TOP%/bin/x86_win32;%path%

set LIB=%TOP%/bin/x86_win32;%LIB%

set INCLUDE=%TOP%/include;%INCLUDE%

set VcOsDir=

set VSCommonDir=

 

如果你的电脑VC的环境变量已经设定在你的环境变量中,那么C:/Program Files/Microsoft Visual
Studio/VC98/Bin/VCVARS32.BAT 就可以不运行。否则运行omni.bat前要首先运行VCVARS32.BAT。

 








回页首

实践过程

 

约定所有编写的文件保存在D:/mywork/t1中,omni.bat也在这个目录内

3.1. 编写SysProp.idl,功能是返回系统属性

 

interface SysProp

{  string getProperty(in string name);

};

 

3.2. 编写JAVA的服务器

 

3.2.1. 把IDL文件转化为JAVA编程语言代码存根类及helper类。

执行如下命令

idlj -fall SysProp.idl

 

在正常的情况下D:/mywork/t1 目录内将生成以下文件,否则请检查你的执行程序及文件

SysProp.java

SysPropHelper.java

SysPropHolder.java

SysPropOperations.java

_SysPropImplBase.java

_SysPropStub.java

3.2.2. 编写 SysPropServer.java

import org.omg.CosNaming.*;

import org.omg.CORBA.*;

 

//编写相对应的服务,一定要从 _类名ImplBase继承,并实现相应的方法
class SysPropS extends _SysPropImplBase //具体的服务实现

{  public String getProperty(String key)

{

System.out.println("调用"+key);

String S;

S=System.getProperty(key);

if (S==null)   { S="null"; }

System.out.println(key+"="+S);

return S;

}

}

public class SysPropServer          //起动服务的程序

{  public static void main(String args[])

{  try

{  System.out.println("创建和初始化 ORB ");

ORB orb = ORB.init(args, null);

System.out.println("创建服务对象并将其向 ORB 注册 ");

SysPropS impl = new SysPropS();

orb.connect(impl);

//打印IOR字符串

System.out.println(orb.object_to_string(impl));

org.omg.CORBA.Object namingContextObj =orb.resolve_initial_references("NameService");
NamingContext namingContext= NamingContextHelper.narrow(namingContextObj);

NameComponent[] path = {new NameComponent("SysProp", "")};

System.out.println("绑定服务...SysPropS");

namingContext.rebind(path, impl);

System.out.println("等待调用...SysPropS");

java.lang.Object sync = new java.lang.Object();

synchronized (sync)

{  sync.wait();

}

}

catch (Exception e)

{   System.err.println("Error: " + e);

e.printStackTrace(System.out);

}

}

}

 

3.3. 编写JAVA的客户机

 

3.3.1. 编写 SysPropClient.java 使用IOR字符串的方式

注意在代码内有一段注解掉的代码,用"//使用ORB的方法的开始"开始,用"//使用ORB的方法的结束"结束。这段代码是使用
ORB方法的代码,如果在代码中"//使用IOR的方法开始"前一行添加"/*",在"//使用IOR的方法结束"后一行添加"*/",而把"//使用
ORB的方法的开始"前面的"/*"去掉,把"//使用ORB的方法的结束"后面的"*/"去掉,就是使用ORB方法的代码,程序运行时就是"
SysPropClient [环境变量] "的方式。以下是具体代码:

import org.omg.CosNaming.*;

import org.omg.CORBA.*;
public class SysPropClient

{

public static void main(String args[])

{

try{

String SetInfo,ReturnInfo,ref;

org.omg.CORBA.Object objRef;

SysProp syspropRef;

ORB orb = ORB.init(args, null);

//使用IOR的方法开始

if (args.length>=1)

{

ref=args[0];

}

else

{

System.out.println("SysPropClient <IOR字符串> [环境变量]");

return;

}

objRef = orb.string_to_object(ref);

syspropRef = SysPropHelper.narrow(objRef);

//使用IOR的方法结束

/*

//使用ORB的方法的开始

objRef = orb.resolve_initial_references("NameService");

NamingContext ncRef = NamingContextHelper.narrow(objRef);

// 进行服务定位

NameComponent nc = new NameComponent("SysProp", "");

NameComponent path[] = {nc};

syspropRef = SysPropHelper.narrow(ncRef.resolve(path));

//使用ORB的方法的开始结束

*/

if (args.length>1)

{

SetInfo=args[1];

}

else

{

SetInfo="java.home";

}

System.out.println("开始调用");

ReturnInfo = syspropRef.getProperty(SetInfo);

System.out.println(SetInfo+"="+ReturnInfo);

} catch (Exception e) {

System.out.println("ERROR : " + e) ;

}

}

}

 

3.3.2. 编译程序,在文件目录内执行如下命令

jAVAC *.JAVA

3.4. 进行测试

 

第1控制台,执行

tnameserv

测试时如下所示

D:/mywork/t1>java tnameserv

Initial Naming Context:

IOR:000000000000002849444c3a6f6d672e6f72672f436f734e616d696e672f4e616d696e67436f

6e746578743a312e3000000000010000000000000054000101000000000c3139322e3136382e302e

31000ca6000000000018afabcafe00000002a999c474000000080000000000000000000000010000

0001000000140000000000010020000000000001010000000000

TransientNameServer: setting port for initial object references to: 900

Ready.

 

第2控制台,执行

java SysPropServer

测试时如下所示

D:/mywork/t1>java SysPropServer

创建和初始化 ORB

创建服务对象并将其向 ORB 注册

IOR:000000000000001049444c3a53797350726f703a312e30000000000100000000000000540001

01000000000c3139322e3136382e302e31000ca7000000000018afabcafe00000002a999dbeb0000

00080000000000000000000000010000000100000014000000000001002000000000000101000000

0000

绑定服务...SysPropS

等待调用...SysPropS

 

第3控制台,执行

java SysPropClient IOR:XXX JAVA.HOME

测试时如下所示

D:/mywork/t1>java SysPropClient IOR:000000000000001049444c3a53797350726f703a312e

3000000000010000000000000054000101000000000c3139322e3136382e302e31000ca700000000

0018afabcafe00000002a999dbeb0000000800000000000000000000000100000001000000140000

000000010020000000000001010000000000 java.home

开始调用

java.home=D:/bea/jdk130/jre

 

3.5. 编写C++的IOR客户机

 

从实践来讲编写C++的客户机程序同JAVA没有多大的区别,只不过JAVA是用idlj生成代码存根类及helper类,而omni是用omniidl来生成代码存根类及helper类,而编程思想及编码过程非常相似。

由于C++的程序要调用omni及VC6的相关文件,所以进入控制台后,如果VC没有进行环境变量设定,那么要先运行
C:/Program Files/Microsoft Visual Studio/VC98/Bin/VCVARS32.BAT
,再运行omni.bat,否则直接运行omni.bat后再编译程序及运行程序。

3.5.1. 把IDL文件转化为C++编程语言代码存根类及helper类。

执行如下命令

omniidl -bcxx SysProp.idl

在正常的情况下D:/mywork/t1 目录内将生成C++编程语言的代码存根类及helper类SysProp.hh和SysPropSK.cc。否则请检查你的执行程序及文件。

3.5.2. 编写SysPropC.cc

#include <iostream.h>

#include <SysProp.hh>

int main(int argc, char** argv)

{

try {

CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "omniORB3");

if( argc < 2 || argc > 3 ) {

cout << "usage:  SysPropC <IOR字符串> [环境变量名]" << endl;

return 1;

}

CORBA::Object_var obj = orb->string_to_object(argv[1]);

SysProp_ptr echoref = SysProp::_narrow(obj);

if( CORBA::is_nil(echoref) ) {

cerr << "没有对象" << endl;

return 1;

}

const char* message;

if (argc==3)

{

message=argv[2];

}

else

{

message="java.home";

}

CORBA::String_var dest = echoref->getProperty(message);

cout <<  (char*)message << "=" <<(char*)dest << endl;

orb->destroy();

}

catch(...) {

cerr << "Caught unknown exception." << endl;

}

return 0;

}

 

3.5.3. 编写dirc.mak,如下所示

TOP = C:/omni

OMNI_DYNAMIC_LIB = msvcstub.lib -NODEFAULTLIB:libcmt.lib -NODEFAULTLIB:libcmtd.lib

CORBA_CPPFLAGS = -D__WIN32__ -D__x86__ -D__NT__ -D__OSVERSION__=4

CORBA_LIB      = omniORB304_rt.lib omnithread2_rt.lib /

$(OMNI_DYNAMIC_LIB) /

wsock32.lib advapi32.lib /

-libpath:$(TOP)/lib/x86_win32

CXXFLAGS       = -O2 -MD -GX $(CORBA_CPPFLAGS) $(DIR_CPPFLAGS)

CXXLINKOPTIONS =

.SUFFIXES: .cc

.cc.obj:

cl /nologo /c $(CXXFLAGS) /Tp$<

all:: SysPropC.exe

SysPropC.exe: SysPropSK.obj SysPropC.obj

link -nologo $(CXXLINKOPTIONS) -out:$@ $** $(CORBA_LIB)

clean::

-del *.obj

-del *.exe

veryclean::

-del *.obj

-del echoSK.* echo.hh

-del *.exe

SysProp.hh SysPropSK.cc: SysProp.idl

$(TOP)/bin/x86_win32/omniidl -T -bcxx -Wbh=.hh -Wbs=SK.cc -Wbtp SysProp.idl

 

3.5.4. 编译程序,执行如下命令

nmake -f dirc.mak

3.5.5. 测试 

在第4控制台

SysPropC IOR:XXX JAVA.HOME

本测试如下所示

D:/mywork/t1>syspropc IOR:000000000000001049444c3a53797350726f703a312e3000000000

010000000000000054000101000000000c3139322e3136382e302e31000ca7000000000018afabca

fe00000002a999dbeb00000008000000000000000000000001000000010000001400000000000100

20000000000001010000000000 os.name

os.name=Windows 2000

 

3.6. 编写C++的NAME方式客户机

 

为了使用NANE方式,必须为OMNI软件设置注册表信息,要在注册表中建立如下数据项(regedit)HKEY_LOCAL_MACHINE/SOFTWARE/ORL/omniORB/2.0/NAMESERVICE(字符串)。

NAMESERVICE的值为tnameserv(jdk1.3/bin内的程序)启动的IOR值(第一次设置时自行添加)。

注意为了使用这种方式每次起动tnameserv后要用新IOR值换去旧的IOR值,我测试过用omini的
omniNames.exe程序做服务器,IOR值是不变的,但服务器用JVAV编写就会出错。如果起动tnameserv,用
c编写的服务器及客户机就可以在上面运行。本例子如下所示

Initial Naming Context:

IOR:000000000000002849444c3a6f6d672e6f72672f436f734e616d696e672f4e616d696e67436f

6e746578743a312e3000000000010000000000000054000101000000000c3139322e3136382e302e

31000ca6000000000018afabcafe00000002a999c474000000080000000000000000000000010000

0001000000140000000000010020000000000001010000000000

TransientNameServer: setting port for initial object references to: 900

Ready.

 

那么就要把从 IOR:开始(含IOR:)后面的字符串放进注册表。

3.6.1. 编写SysPropCC.cc

//使用NAME方式的客户机

#include <iostream.h>

#include "SysProp.hh"

static CORBA::Object_ptr getObjectReference(CORBA::ORB_ptr orb);

int main (int argc, char **argv)

{

if(  argc != 2 ) {

cout << "使用方法: SysPropCC  <环境变量名>" << endl;

return 1;

}

try {

CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "omniORB3");

CORBA::Object_var obj = getObjectReference(orb);

SysProp_ptr echoref = SysProp::_narrow(obj);

const char* message;

if (argc==2){message=argv[1];}

else {message="java.home"; }

CORBA::String_var dest = echoref->getProperty(message);

cout <<  (char*)message << "=" <<(char*)dest << endl;

orb->destroy();

}

catch(...) { cerr << "Caught unknown exception." << endl; }

return 0;

}

//////////////////////////////////////////////////////////////////////

static CORBA::Object_ptr getObjectReference(CORBA::ORB_ptr orb)

{

CosNaming::NamingContext_var rootContext;

try {

// 定位服务器:

CORBA::Object_var obj;

obj = orb->resolve_initial_references("NameService");

// Narrow the reference returned.

rootContext = CosNaming::NamingContext::_narrow(obj);

if( CORBA::is_nil(rootContext) ) {

cerr << " 初始化不成功." << endl;

return CORBA::Object::_nil();

}

}

catch(CORBA::ORB::InvalidName& ex) {

cerr << " 没有找到服务" << endl;

return CORBA::Object::_nil();

}

CosNaming::Name name;

name.length(1);

name[0].id   = (const char*) "SysProp";

name[0].kind = (const char*) "";

try {

// Resolve the name to an object reference.

return rootContext->resolve(name);

}

catch(...) {  cerr << "定位不成功." << endl;}

return CORBA::Object::_nil();

}

 

3.6.2. 编写dircc.mak

TOP = C:/omni

DIR_CPPFLAGS   = -I. -I$(TOP)/include

OMNI_DYNAMIC_LIB = msvcstub.lib -NODEFAULTLIB:libcmt.lib -NODEFAULTLIB:libcmtd.lib

CORBA_CPPFLAGS = -D__WIN32__ -D__x86__ -D__NT__ -D__OSVERSION__=4

CORBA_LIB      = omniORB304_rt.lib omnithread2_rt.lib /

$(OMNI_DYNAMIC_LIB) /

wsock32.lib advapi32.lib /

-libpath:$(TOP)/lib/x86_win32

CXXFLAGS       = -O2 -MD -GX $(CORBA_CPPFLAGS) $(DIR_CPPFLAGS)

CXXLINKOPTIONS =

.SUFFIXES: .cc

.cc.obj:

cl /nologo /c $(CXXFLAGS) /Tp$<

all:: SysPropCc.exe

SysPropCc.exe: SysPropSK.obj SysPropCc.obj

link -nologo $(CXXLINKOPTIONS) -out:$@ $** $(CORBA_LIB)

clean::

-del *.obj

-del *.exe

veryclean::

-del *.obj

-del echoSK.* echo.hh

-del *.exe

SysProp.hh SysPropSK.cc: SysProp.idl

$(TOP)/bin/x86_win32/omniidl -T -bcxx -Wbh=.hh -Wbs=SK.cc -Wbtp SysProp.idl

 

3.6.3. 编译文件


nmake -f dircc.mak


3.6.4. 测试

在第5控制台

SysPropCC JAVA.HOME


测试结果如下所示

D:/mywork/t1>syspropcc java.home

java.home=D:/bea/jdk130/jre








回页首

小结

 

另还使用了j2sdkee1.2.1进行测试,由于j2sdkee1.2.1起动时的nameserver的PORT是1050
所以启动服务要加参数,对于本文中的程序运行时要如下所示:

java SysPropServer -ORBInitialPort 1050

如果用IOR的方式,也可以用omni的omniNames.exe程序做命名服务器,用C++编写服务器,客户机使用Java和C++编写,c++编写服务器的例子可见omni的文档。

本次只是简单进行了测试,可以使大家了解一下,CORBA的这种特性,多种不同程序语言进行协作编程的具体运作过程,希望可以抛砖引玉。

参考资料

《JAVA2核心技术 卷II:高级特性》(对于omniORB是2.0的例子)

《The omniORB version 3.0 User's Guid》(omniORB软件内自带)

关于作者



王辉,具有八年的编程及系统管理经验,所使用的语言为C和Java 编程语言。目前在深圳一家公司做分析员,使用C和JAVA为DB2数据库编程。可通过
ddxxkk@21cn.com
联系。

摘自:http://www.ibm.com/developerworks/cn/java/l-jccorba/index.html

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息