摘 要:本文在对CORBA体系原理进行探讨的基础上,给出CORBA体系结构下跨平台分布式应用程序的开发方法。给出的实例将在Linux环境下开发CORBA服务器组件,在Windows下构建客户程序对该组件进行调用。
关键词:CORBA 分布式应用程序
一、引言
计算机网络是典型的异构(Heterogeneous)体系。Unix、Linux、 Windows的多操作系统平台在同一网络中长期共存,性能各异的各种计算机,操作平台,网络平台的组合使软件系统的开发日趋朝着分布式方向迈进。CORBA体系结构为开发平台无关的组件提供了完整的解决方案,这种体系结构为开发大型的分布式异构应用软件系统提供了独立于硬件平台、独立于计算机操作系统和独立于网络传输协议的平台。CORBA现在已成为中间件软件开发技术的主流,在分布式软件系统的开发中发挥着日益重要的作用,但CORBA体系抽象而难以理解,再加上这方面的参考文献不是很多,这在一定程度上制约了CORBA的应用与发展。本文在深入浅出分析CORBA原理的基础上,给出跨平台CORBA程序的构建方法,旨在通过实际应用来加深对CORBA的理解,掌握基于CORBA的分布式程序开发流程。
二、CORBA原理、体系概述
CORBA(公共对象请求代理结构)是OMG组织(对象管理组织)提出的公用对象请求代理程序结构的技术规范。对象请求代理(ORB, Object Request Broker)是CORBA的基础,它负责解决对象引用的请求和建立应用对象之间的连接,通过标准接口使这种连接独立于所使用的硬件和软件平台,从而保证了对平台的透明性以及对操作系统、网络协议和编程语言的透明性。图1给出了客户向服务(对象实现)发送请求的过程。
ORB提供了如下支持分布式处理的机制:为请求查找具体的对象实现、让对象实现做好接收请求的准备、传送构成请求的数据等。客户所看到的接口完全独立于对象所在的物理位置、对象实现的编程语言以及在对象的接口中没有反映出来的特性。图2给出了一个单独的对象请求代理(ORB)的结构,其中条形框表示ORB所提供的接口。
为了调用一个分布式对象的操作,客户机必须了解由这个对象所提供的接口。一个对象的接口是由它所支持的操作和能够来回传输给这些操作的数据类型所组成的。在CORBA中,对象接口是按OMG接口定义语言(IDL)来定义的。IDL独立于任何编程语言,用IDL编译器可以将它映射为其他常用的语言如C++, Java等。
在此,我们给出一个典型的CORBA调用的过程,如图3所示,也是我们下面的实际实例的工作过程。
首先用IDL定义好CORBA组件的接口,然后由ORB厂商提供的IDL编译器根据一定的规则编译IDL文件生成客户端根程序(Client Stub)和服务器端框架程序(Server Skeletons)。 服务器端组件实现编写完成后在ORB环境中运行等待客户的调用,客户程序通过根程序发出对服务的调用,服务器通过框架程序完成对客户请求的响应,当然客户程序也可通过动态调用对服务器发出请求,而服务器也可以通过动态程序框架予以响应。客户程序的请求方式和服务程序的响应方式没有一一对应关系,至于根程序如何通过网络访问服务器以及服务器如何将调用结果传给客户都由ORB核心完成而不需要我们关心。
三、CORBA 分布式应用程序开发流程
在开发基于CORBA的应用程序前最重要的就是要配置好CORBA环境,特别是Linux下的环境。这要依据用户选用的CORBA产品进行不同的安装设置。本文的Linux环境为Red Hat 7.3,ORB服务选用Borland的Visibroker。为了突出跨平台应用程序的主题,本文只演示一个简单的例子,麻雀虽小,五脏俱全,这足以说明开发的完整过程。
3.1 Linux下的服务器端程序开发
1、 使用接口定义语言(IDL)定义接口。
module FirstModule{
interface TestInterface{
string GetTestString();
};
};
用vim等文本编辑器编辑上述idl文件,存为FirstModule.idl。在该idl文件中定义了接口TestInterface,这个接口的一个方法GetTestString。
2.用IDL 编译器生成客户端存根代码和服务器端框架代码。Visibroker提供的C++ idl编译器为idl2pp。
[root@duxiaoping forlinux]# /home/BES/bin/idl2cpp -boa FirstModule.idl
生成FirstModule_c.cc FirstModule_c.hh FirstModule_s.cc FirstModule_s.hh四个文件。FirstModule_s.cc为服务器框架程序,我们看看根据idl文件生存的框架类定义文件FirstModule_s.hh:
// in FirstModule_s.hh
#include "FirstModule_c.hh"
class _sk_FirstModule {
public:
class _sk_TestInterface : public POA_FirstModule::TestInterface,
public PortableServer_RefCountServantBase,
public FirstModule::TestInterface {
...
};
};
我们服务器端的接口实现要继承自_sk_FirstModule::_sk_TestInterface,其实这个类的生成不是必然的,为了简化我们只演示一个BOA的实例,上面在idl编译器选项上加了-boa参数,如果没有这个参数,将只生成基于可移植对象适配器(POA)的框架:
class POA_FirstModule {
public:
class TestInterface : public FirstModule::TestInterface_ops ,public virtual PortableServer_ServantBase {
...
};
};
2、 接口实现
// TestInterfaceServer.h
#include "FirstModule_s.hh"
class TestInterfaceImpl: public _sk_FirstModule::_sk_TestInterface{
protected:
public:
TestInterfaceImpl(const char *object_name=NULL);
char* GetTestString();
};
// TestInterfaceServer.cpp
#include <corba.h>
#include "TestInterfaceServer.h"
TestInterfaceImpl::TestInterfaceImpl(const char *object_name):
_sk_FirstModule::_sk_TestInterface(object_name){
}
// 接口中唯一的方法实现
char* TestInterfaceImpl::GetTestString(){
cout << “the TestInterfaceImpl::GetTestString() was called!”
return CORBA::string_dup("Only a test!");
}
3、 服务器端主程序
// FirstServer.cpp
#include "FirstModule_c.hh"
#include "TestInterfaceServer.h"
#include <corba.h>
main(int argc, char* argv[])
{ //1. 初始化ORB
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
//2. 初始化BOA
CORBA::BOA_var boa = orb->BOA_init(argc, argv);
//3. 生成CORBA服务器实现对象
TestInterfaceImpl testInterface_TestInterfaceObject("TestInterfaceObject");
boa->obj_is_ready(&testInterface_TestInterfaceObject);
//4. 等待调用请求
cout << “the TestInterfaceObject is ok...” << endl;
boa->impl_is_ready();
}
}
4、 编译生成CORBA服务器程序
[root@duxiaoping forlinux]# g++ -D_REENTRANT -DTHREAD -DPTHREADS -o FirstServer -I/home/BES/include -I/home/BES/include/stubs -I/usr/include -I/usr/include/kpathsea -L/home/BES/lib -L/usr/lib -L/lib -lcosev_r -lcosnm_r -lvport_r -lorb_r -ldl -lpthread FirstModule_c.cc FirstModule_s.cc TestInterfaceServer.cpp FirstServer.cpp
3.2 Windows下的客户端程序开发
1. C++Builder集成了CORBA环境,使得开发Windows下的CORBA应用变得简单。
打开C++Builder->file->new->other,选择multitier页面的CorbaClient。
2. 弹出CorbaClient 向导,选择console application,点击Add添加前面生成的idl文件FirstModule.idl。
3. 在Project Manager视窗里面右击FirstModule.idl,在弹出菜单中点击Copmile命令,生成客户端根程序,FirstModule_c.hh和FirstModule_c.cpp程序。
4. 保存客户端工程为FirstClient。在main函数中添加对CORBA服务器实现对象的调用。
在CORBA主菜单中点击Edit->Use Corba Object,在要调用的对象名中填写我们在Linux服务器端的实现对象名称TestInterfaceObject。在main()函数中自动添加了对对象的引用代码:
main(int argc, char* argv[])
{
// 初始化ORB和BOA
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
CORBA::BOA_var boa = orb->BOA_init(argc, argv);
// 对服务器对象的引用
FirstModule::TestInterface_var testInterface = FirstModule::TestInterface::_bind("TestInterfaceObject");
char test[64];
// 调用对象的方法
strcpy(test, testInterface->GetTestString());
cout << test << endl;
}
5.编译工程,生成客户端应用程序FirstClient。
3.3 运行程序
1. 运行Visibroker的智能代理(Visibroker Smart Agent),在Linux下或者Windows都可,只要有一个在运行即可。
[root@duxiaoping forlinux]# /home/BES/bin/osagent
2. 运行服务器程序
[root@duxiaoping forlinux]# FirstServer
the TestInterfaceObject is ok...
此时可以用Visibroker Console应用程序查看对象的运行情况了,如图所示:
Instance Name就是服务实例对象。
图4 用Visibroker Console看到的服务对象 |
3. 运行Windows客户端程序
服务器端马上出现:the TestInterfaceImpl::GetTestString() was called!
四、结论
本文以一个简单的实例介绍了基于CORBA的跨平台分布式应用程序开发方法。CORBA在开发跨平台的分布式应用程序中对程序员屏蔽了大量底层通信细节,CORBA理论虽然较难理解,但在开发工具的配合下实际开发却较为简单,在实际的开发过程中容易加深对复杂概念的理解,这也是本文写作的主要目的。
参考文献:
[1] 朱其亮, 郑斌. CORBA原理及应用. 北京邮电大学出版社,2001
[2] OMG编著,韩乐平,薛军敖,孟洛明编译. CORBA系统结构、原理与规范.电子工业出版社. 2000
[3] Borland Software Corporation. VisiBroker Developer’s Guide. Borland Software Corporation, 2002
|