体验CORBA: 使用java和C++混合编程
来源:互联网 发布:广东网络教育学费多少 编辑:程序博客网 时间:2024/05/10 03:20
1. 前言 72f436f734e616d696e672f4e616d696e67436f6e7 46578743a312e30000000000100000000000000 54000101000000000c3139322e3136382e302e3 1000ca6000000000018afabcafe00000002a999c 474000000080000000000000000000000010000 010000000000 0726f703a312e3000000000010000000000 000054000101000000000c3139322e3136 382e302e31000ca7000000000018afabcaf e00000002a999dbeb00000008000000000 0000000000000010000000100000014000 0000000010020000000000001010000000 000 0726f703a312e3000000000010000000000 000054000101000000000c3139322e3136 382e302e31000ca7000000000018afabcaf e00000002a999dbeb00000008000000000 0000000000000010000000100000014000 0000000010020000000000001010000000000 java.home 3a312e30000000000100000000000000540001010 00000000c3139322e3136382e302e31000ca70000 00000018afabcafe00000002a999dbeb0000000800 00000000000000000000010000000100000014000 0000000010020000000000001010000000000 os.name 6f734e616d696e672f4e616d696e67436f6e746578743a 312e30000000000100000000000000540001010000000 00c3139322e3136382e302e31000ca6000000000018af abcafe00000002a999c47400000008000000000000000 000000001000000010000001400000000000100200000 00000001010000000000
现在很多人在对CORBA进行学习,大家都已经了解到CORBA是一个完全中间性的语言,可以使用接口定义语言(IDL)定义开发时使用接口的 Client 和实现接口的 Server 所需要的信息。Client 和 Server 的具体实现代码并不在IDL定义中编写,而是使用某种目标语言的IDL 编译器生成所需的代码存根及helper类,Client 和 Server再使用真正的编程语言来进行具体实现。
为了保证在不同的 CORBA 产品基础之上构建的分布式对象可以相互通信,Client和Server通过ORB(对象请求代理)进行通信。一般的运行流程是Client把请求发送给ORB,ORB再把请求发送给Server,Server把返回结果发送ORB,ORB再把返回结果发送给Client。ORB可以说Client和Server之间的翻译者。即使Client和Server使用不同的编程语言编写,只要是符合相同的IDL定义,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++编写的客户机分别调用相应的服务
2. 运行环境的设定:
总体环境由jdk1.3+omniORB3.0(www.uk.research.att.comomniORBdoc3.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 FilesMicrosoft Visual Studio
2.3. 安装omniORB
从 http://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:omniREADME.win32 文档进行设定,由于运行程序及命令行在控制台进行,所以本次测试并不根据文档要求去设定环境变量,而是编写了一个omni.bat,在使用控制台时,首先运行。
本测试电脑omni.bat内容如下
set TOP=c:omni
set path=%TOP%binx86_win32;%path%
set LIB=%TOP%binx86_win32;%LIB%
set INCLUDE=%TOP%include;%INCLUDE%
set VcOsDir=
set VSCommonDir=
如果你的电脑VC的环境变量已经设定在你的环境变量中,那么C:Program FilesMicrosoft Visual StudioVC98BinVCVARS32.BAT 就可以不运行。否则运行omni.bat前要首先运行VCVARS32.BAT。
3. 实践过程
约定所有编写的文件保存在D:myworkt1中,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:myworkt1 目录内将生成以下文件,否则请检查你的执行程序及文件
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 [环境变量]");
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:myworkt1>java tnameserv
Initial Naming Context:
IOR:000000000000002849444c3a6f6d672e6f726
000100000014000000000001002000000000001
TransientNameServer: setting port for initial object references to: 900
Ready.
第2控制台,执行
java SysPropServer
测试时如下所示
D:myworkt1>java SysPropServer
创建和初始化 ORB
创建服务对象并将其向 ORB 注册
IOR:000000000000001049444c3a5379735
绑定服务...SysPropS
等待调用...SysPropS
第3控制台,执行
java SysPropClient IOR:XXX JAVA.HOME
测试时如下所示
D:myworkt1>java SysPropClient IOR:000000000000001049444c3a5379735
开始调用
java.home=D:beajdk130jre
3.5. 编写C++的IOR客户机
从实践来讲编写C++的客户机程序同JAVA没有多大的区别,只不过JAVA是用idlj生成代码存根类及helper类,而omni是用omniidl来生成代码存根类及helper类,而编程思想及编码过程非常相似。
由于C++的程序要调用omni及VC6的相关文件,所以进入控制台后,如果VC没有进行环境变量设定,那么要先运行C:Program FilesMicrosoft Visual StudioVC98BinVCVARS32.BAT,再运行omni.bat,否则直接运行omni.bat后再编译程序及运行程序。
3.5.1. 把IDL文件转化为C++编程语言代码存根类及helper类。
执行如下命令
omniidl -bcxx SysProp.idl
在正常的情况下D:myworkt1 目录内将生成C++编程语言的代码存根类及helper类SysProp.hh和SysPropSK.cc。否则请检查你的执行程序及文件。
3.5.2. 编写SysPropC.cc
#include
#include
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 [环境变量名]" << 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)libx86_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)binx86_win32omniidl -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:myworkt1>syspropc IOR:000000000000001049444c3a53797350726f70
os.name=Windows 2000
3.6. 编写C++的NAME方式客户机
为了使用NANE方式,必须为OMNI软件设置注册表信息,要在注册表中建立如下数据项(regedit)HKEY_LOCAL_MACHINESOFTWAREORLomniORB2.0NAMESERVICE(字符串)。
NAMESERVICE的值为tnameserv(jdk1.3bin内的程序)启动的IOR值(第一次设置时自行添加)。
注意为了使用这种方式每次起动tnameserv后要用新IOR值换去旧的IOR值,我测试过用omini的omniNames.exe程序做服务器,IOR值是不变的,但服务器用JVAV编写就会出错。如果起动tnameserv,用 c编写的服务器及客户机就可以在上面运行。本例子如下所示
Initial Naming Context:
IOR:000000000000002849444c3a6f6d672e6f72672f43
TransientNameServer: setting port for initial object references to: 900
Ready.
那么就要把从 IOR:开始(含IOR:)后面的字符串放进注册表。
3.6.1. 编写SysPropCC.cc
//使用NAME方式的客户机
#include
#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)libx86_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)binx86_win32omniidl -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:myworkt1>syspropcc java.home
java.home=D:beajdk130jre
4. 小结
另还使用了j2sdkee1.2.1进行测试,由于j2sdkee1.2.1起动时的nameserver的PORT是1050所以启动服务要加参数,对于本文中的程序运行时要如下所示:
java SysPropServer -ORBInitialPort 1050
如果用IOR的方式,也可以用omni的omniNames.exe程序做命名服务器,用C++编写服务器,客户机使用Java和C++编写,c++编写服务器的例子可见omni的文档。
本次只是简单进行了测试,可以使大家了解一下,CORBA的这种特性,多种不同程序语言进行协作编程的具体运作过程,希望可以抛砖引玉。
- 体验CORBA: 使用java和C++混合编程
- 亲身体验CORBA: 使用java和C++混合编程
- 体验CORBA: 使用java和C++混合编程
- 亲身体验CORBA: 使用java和C++混合编程
- 亲身体验CORBA: 使用java和C++混合编程
- 基于Corba技术使用java与C++混合编程
- 使用java和CORBA实现分布应用编程
- C和C++混合编程(__cplusplus使用)
- C和C++混合编程(__cplusplus使用)
- C和C++混合编程(__cplusplus使用)
- 使用 CORBA 和 Java IDL
- C++&Java混合编程
- 使用Java进行CORBA编程-JacORB-入门
- C和C++混合编程(extern C 和__cplusplus使用)
- C和C++混合编程之 extern “C”的使用
- 使用IBM Java Toolbox实现Java/C混合编程
- Java&CORBA编程实例
- 使用JNI进行Java与C/C++语言混合编程
- CORBA Programming with TAO - 6.Naming Service(使用命名服务)
- container_of深入理解
- linux下遍历目录树方法总结
- 我是菜鸟之小小项目开发经历(三)------第一个应用系统开发
- poj 1556
- 体验CORBA: 使用java和C++混合编程
- Corba入门程序调试C(2)通过IOR---omniORB
- Linux/Unix网络编程之UDP的connect函数
- Android 通过network gps获取当前位置的location信息
- CORBA Programming with TAO - 5.Hello World(简单实例)
- CORBA Programming with TAO - 5.Hello World(简单实例)
- 用RegNotifyChangeKeyValue() 设置与注册表项长期关联
- CORBA Programming with TAO - 4.Basic Functions(常用基本方法解析)
- 击退