一 实习目的
通过实例掌握CORBA的开发过程:主要包括:接口定义;接口的对象实现;服务器端代码编写;客户端代码编写;CORBA Server/Client的编译与运行;
二 实习要求
1)基于CORBA技术开发一个考试成绩查询系统,主要包括:服务器部分:实现查询和录入服务;客户端部分包括录入和查询部分
2)服务端使用Java编写,使用JDBC访问数据库;客户端使用Java和C++分别编写。
三 实习过程
实验准备
1、下载omniORB
https://download.csdn.net/download/qq_44859217/12412569
2、环境变量
将java/bin以及omniORB/bin配置在环境变量path中。
实验内容
A.服务接口定义,在
W
o
r
k
h
o
m
e
Work_home
Workhome下,编写DataService.idl,定义查询与录入函数.
B.Java实现Corba服务器端。
1)用以下命令生成存根与框架:
idlj -fall DataService.idl
2)在
W
o
r
k
h
o
m
e
Work_home
Workhome下,创建server文件夹,并将1)得到的存根和框架java文件拷贝至server,并使用eclipse创建一工程,将这些文件包含进去。
3)编写服务端服务实现,并写main函数以启动corba服务。
编写的DataServiceServer.java的代码如下:
package server;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
import org.omg.CosNaming.*;
import org.omg.PortableServer.*;
import server.DBmanager;
//编写相对应的服务,一定要从 _类名ImplBase继承,并实现相应的方法
class DataServiceImpl extends DataServicePOA // 具体的服务实现
{
private ORB orb;
public void setOrb(ORB orb_val) {
this.orb = orb_val;
}
@Override
public void insert(String stuName, String StuNo, float score) {
// TODO Auto-generated method stub
DBmanager.insert(stuName, StuNo, score);
}
@Override
public float search(String stuNo) {
// TODO Auto-generated method stub
return DBmanager.search(stuNo);
}
}
public class DataServiceServer// 起动服务的程序
{
public static void main(String args[]) {
try {
System.out.println("创建和初始化 ORB ");
ORB orb = ORB.init(args, null);
POA rootpoa = POAHelper.narrow(orb
.resolve_initial_references("RootPOA"));
rootpoa.the_POAManager().activate();
System.out.println("创建服务对象并将其向 ORB 注册 ");
DataServiceImpl dataServiceImpl = new DataServiceImpl();
dataServiceImpl.setOrb(orb);
// System.out.println(orb.object_to_string(sysProImpl));
org.omg.CORBA.Object objRef = orb
.resolve_initial_references("NameService");
NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
NameComponent[] path = { new NameComponent("DataService", "") };
org.omg.CORBA.Object ref = rootpoa
.servant_to_reference(dataServiceImpl);
DataService href = DataServiceHelper.narrow(ref);
System.out.println(orb.object_to_string(href));
System.out.println(ncRef.getClass().toString());
ncRef.rebind(path, href);
System.out.println("DataServiceServer ready and waiting ...");
orb.run();
} catch (Exception e) {
System.err.println("Error: " + e);
e.printStackTrace(System.out);
}
}
}
在工程中创建DBmanager类,用来连接mysql数据库,DBmanager.java的代码如下:
package server;
import java.sql.*;
public class DBmanager {
private static Connection conn;
private static Statement sta;
private static ResultSet result;
private static String driver = "com.mysql.jdbc.Driver";
private static String url = "jdbc:mysql://localhost:3306/mycorba";
private static float score;
public static Connection getcon() {
Connection con = null;
try {
Class.forName(driver);// 注册驱动
} catch (ClassNotFoundException e) {
System.out.println("未完成注册驱动");
e.printStackTrace();
}
try {
con = DriverManager.getConnection(url, "root", "123456");// 建立连接
} catch (SQLException e) {
// TODO: handle exception
System.out.println("未完成数据连接");
e.printStackTrace();
}
return con;
}
public static void insert(String stuName, String StuNo, float score) {
try {
conn = getcon();
String sql = "insert into mytable(stuName,stuNo,score) values(?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.clearBatch();
ps.setString(1, stuName);
ps.setString(2, StuNo);
ps.setFloat(3, score);
ps.addBatch();
ps.executeBatch();
ps.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static float search(String StuNo) {
try {
conn = getcon();
String sql = "select * from mytable where StuNo=" + StuNo;
sta = conn.createStatement();
result = sta.executeQuery(sql);
if (result.next()) {
String stuName = result.getString(1);
String stuNo = result.getString(2);
score = result.getFloat(3);
}
sta.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
return score;
}
}
C.Java实现Corba客户端。
1)在
W
o
r
k
h
o
m
e
Work_home
Workhome下,创建java_client文件夹,并将B的1)得到的存根和框架java文件拷贝至java,并使用eclipse创建一工程,将这些文件包含进去。
2)编写客户端对查询与录入的调用.
package client;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
public class DataServiceClient {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
String SetInfo, ReturnInfo, ref;
float score = 0;
org.omg.CORBA.Object objRef;
DataService dataserviceRef;
ORB orb = ORB.init(args, null);
/*
* if (args.length >= 1) { ref = args[0]; //System.out.println(ref);
* } else { System.out.println("aaaaaaaaaaaaaaaaaa"); return ; }
*/
// 下面一条语句得到的是一个NamingContext对象,并非SysProp对象
// objRef = orb.string_to_object(ref);
// dataserviceRef = DataServiceHelper.narrow(objRef);
objRef = orb.resolve_initial_references("NameService");
System.out.println(orb.object_to_string(objRef));
NamingContext ncRef = NamingContextHelper.narrow(objRef);
NameComponent nc = new NameComponent("DataService", "");
NameComponent path[] = { nc };
dataserviceRef = DataServiceHelper.narrow(ncRef.resolve(path));
if (args.length > 1) {
SetInfo = args[1];
} else {
SetInfo = "0";
}
System.out.println("开始调用");
System.out.println("运行成功!");
System.out.println("**********成绩录入**************");
dataserviceRef.insert("zjc", "2017013204", 100);
System.out.println("成绩录入成功!\n");
System.out.println("**********成绩查询**************");
String searchStuNo = "2017013204";
float getScore = dataserviceRef.search(searchStuNo);
System.out.println("学号 "+searchStuNo+" 的成绩为: "+getScore);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3)创建数据库
在MySQL中创建数据库mycobra,在数据库中建表mytable
D.C++实现Corba客户端。
需要安装vc6.0。
1)用以下命令生成存根与框架:
omniidl -bcxx DataService.idl
得到*.hh文件和*.cc文件,将后缀名改为*.h和*.cpp,并在*.cpp文件中#include “.hh” 改为#include “.h”.
2)在
W
o
r
k
h
o
m
e
Work_home
Workhome下,创建C_client文件夹, 并将1)所得到的文件拷贝至C_client。使用Vc++6.0创建一工程,工程路径指向
W
o
r
k
h
o
m
e
Work_home
WorkhomeC_client,并将存根与框架程序加入工程。
3)配置vc环境。
Tools–>Options选择Directory标签,在Include files下加入omniORB的lib和include路径
在Library files下加入omniORB的lib路径
Project–>Setting,选择C++,分别对C++ Language,Code Generation,Preprocessor进行设置
C++ Language下勾选“Enable Exception Handling
Code Generation下的Use runtime library选择Multithreaded DLL
Preprocessor添加宏定义
“WIN32,x86,_WIN32_WINNT=0x0400,NT,OSVERSION=4”
选择Link选项卡,Category选择Input,添加库模块
ws2_32.lib mswsock.lib advapi32.lib omniORB410_rt.lib omniDynamic410_rt.lib omnithread33_rt.lib
填写附加库路径,我的为“D:\omniORB-4.1.0\lib\x86_win32 ”
4)编写客户端调用。
这里的IOR要复制服务器端产生的那个。
#include "DataService.h"
#include <stdio.h>
int main(int argc,char* argv[]){
try{
CORBA::ORB_var orb = CORBA::ORB_init(argc,argv);
char* IORStr= "IOR:000000000000001449444c3a44617461536572766963653a312e3000000000010000000000000086000102000000000e3139322e3136382e302e31303500cb3f00000031afabcb000000002006e49b4200000001000000000000000100000008526f6f74504f410000000008000000010000000014000000000000020000000100000020000000000001000100000002050100010001002000010109000000010001010000000026000000020002";
CORBA::Object_var obj = orb->string_to_object(IORStr);
if(CORBA::is_nil(obj)){
printf("Nil Score Reference");
throw 0;
}
DataService_var tm = DataService::_narrow(obj);
if(CORBA::is_nil(tm)){
printf("Nil Score Reference");
throw 0;
}
printf("成绩为 %f\n ",tm->search("2017013204"));
}catch(const CORBA::Exception&){
printf("Exception\n");
return 1;
}
return 0;
}
E.测试
参考corbaExample/command.txt运行程序。
1).启动命名服务
2).启动Java服务器端
启动之前先要启动MySQL,还要注意将MySQL的连接的jar包加入到服务器端工程中
现在启动Java服务器端DataServiceServer.java
3).启动Java客户端
启动Java客户端DataServiceClient.java
数据库显示
4).运行C++客户端
四 遇到的问题
①jdk缺少相应的idlj.exe应用程序,就会出现下面的问题。
原因可能是因为我之前的jdk版本太低或者误删等原因,里面没有idlj.exe应用程序。所及解决方法就是安装一个新版本的jdk。可以看到新版本的jdk的bin目录里有该应用程序。
②VC6.0的闪退问题。
原因应该是window和vc的版本不兼容所导致的。
解决方法从网上下载FileTool.dll文件,并拷贝到VC安装目录的Common\MSDev98\AddIns 文件夹下。然后在DOS命令下手动注册FileTool.dll文件(需要用管理员身份打开),运行:
regsvr32 “VC安装路径\Common\MSDev98\AddIns\FileTool.dll”
最后打开VC,点击Tools–>定制–>附加项和宏文件–>选中 FileTool Developer Studio Add-in 复选框 ,就可以了。
之后打开和添加文件就用这两个按钮,千万不能用原来的,因为还是会退出去。
③IOR问题
运行命名服务出现的DOS界面的IOR、运行服务端产生的IOR以及运行客户端产生的IOR都不一样,在进行c++实现客户端的时候,需要将服务器端产生的IOR复制进去,否则会出现查不到数据库内容的情况。