一 實習目的
通過執行個體掌握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複制進去,否則會出現查不到資料庫内容的情況。