Технология CORBA

Лабораторная работа:

Технология CORBA

Пример 1. Тестирование CORBA-соединения клиента с сервером

Рассмотрим создание примитивной клиент/серверной ИС, состоящей из:

· CORBA-сервера, приветствующего обратившегося к нему CORBA-клиента;

· CORBA-клиента, способного подключаться к CORBA-серверу.

Построение CORBA-сервера

Для построения CORBA-сервера нужно запустить мастера CORBA Server командой File | New | Other | Multitier | CORBA Server (рис. 1).

Рисунок 1

Когда мастер создания сервера запущен, он ожидает от программиста некоторой дополнительной информации (рис. 2):

1. Какого рода CORBA-сервер следует создать: консольное приложение (опция Console Application) или оконное (Window Application)? Не лишне напомнить, что сервер CORBA — это программа, производящая экземпляры объектов и уведомляющая об этом все заинтересованные программы-клиенты.

Рисунок 2

2. Имена IDL-файлов с описанием интерфейсов объектов (кнопка Add) либо, если отметить кнопку Add New IDL File, мастер сам создаст пустой IDL-файл и добавит его в проект.

После нажатия кнопки OK генерируется новый проект, и в окне редактора открывается пустой IDL-файл.

Следующим действием разработчика будет описание интерфейса объекта калькулятора на языке IDL (рис. 5.3).

Рисунок 3

Сохраним полученное описание в файле с именем User.idl.

Теперь можно создать интерфейс пользователя, как показано на рис. 4.

Рисунок 4

В элемент управления Memo1 будет заноситься строка приветствия подключившегося к CORBA-серверу клиента.

Сохраним проект под именем CORBAServerProject.

Для создания импортируемого сервером объекта выполним команду File | New | Other | Multitier | CORBA Object Implementation для запуска соответствующего мастера (рис. 5).

Рисунок 5

Запущенный мастер собирает необходимую для генерации кода информацию (название файла описания объекта на IDL и имя реализуемого интерфейса) и отбражает на экране диалоговое окно (рис. 5.6).

.

Рисунок 6

В поле Interface Name следует выбрать из выпадающего списка имя интерфейса User::Welcome; это приведет к автоматическому заполнению имени класса объекта и модуля, которые будут сгенерированы мастером CORBA Object Implementation. Имя самого объекта WelcomeObject проставляется в поле Object Names. В самом низу диалоговой панели в левой ее стороне находится кнопка Show Updates. Со включенной кнопкой Show Updates программист получает возможность видеть все изменения в проекте, происходящие при генерации новых файлов и автоматической модификации уже имеющихся исходных текстов. После нажатия на кнопку Ok появляется окно (рис. 7), в котором слева отображается список всех произошедших во время работы мастера действий, тогда как в правой панели находятся исходные тексты, являющиеся результатом подобных действий.

Рисунок 7

Эта панель — полноценный редактор, в котором можно тут же внести изменения. Если то или иное действие мастера программиста не устраивает, он может просто отключить кнопку напротив его названия в левой панели. И действие будет отменено. Создавая калькулятор, нужно найти действие с именем WelcomeImpl::Hello (в левой панели), переключиться на него и внутрь пока еще пустого (в правой панели) метода Hello внести код приветствия. Заметим, что для успешной компиляции этого кода в модуль нужно добавить заголовочный файл формы #include «CORBAServerUnit.h«, а ссылку extern TForm1 *Form1;.

Осталось построить проект (рис. 8).

Рисунок 8

CORBAServerProject.cpp

#include <vcl.h>

#pragma hdrstop

//—————————————————————————

#include «WelcomeServer.h»

#include <corba.h>

USEFORM(«CORBAServerUnit.cpp», Form1);

//—————————————————————————

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)

{

try

{

Application->Initialize();

// Initialize the ORB and BOA

CORBA::ORB_var orb = CORBA::ORB_init(__argc, __argv);

CORBA::BOA_var boa = orb->BOA_init(__argc, __argv);

WelcomeImpl welcome_WelcomeObject(«WelcomeObject»);

boa->obj_is_ready(&welcome_WelcomeObject);

Application->CreateForm(__classid(TForm1), &Form1);

Application->Run();

}

catch (Exception &exception)

{

Application->ShowException(&exception);

}

catch (…)

{

try

{

throw Exception(«»);

}

catch (Exception &exception)

{

Application->ShowException(&exception);

}

}

return 0;

}

WelcomeServer.cpp

#pragma hdrstop

#include <corba.h>

#include «WelcomeServer.h»

#include «CORBAServerUnit.h»

//—————————————————————————

#pragma package(smart_init)

extern TForm1 *Form1;

WelcomeImpl::WelcomeImpl(const char *object_name):

_sk_User::_sk_Welcome(object_name)

{

}

void WelcomeImpl::Hello()

{

Form1->Memo1->Lines->Add («Hello, client!»);

}

Интересной особенностью CORBA-мастеров C++ Builder является их умение синхронизировать изменения в описании объектной модели с генерируемыми исходными текстами. Каждый раз, когда программист модифицирует IDL-файл, среда разработки исправляет заглушки (stubs) и скелеты (skeletons) приложения, а также переделывает объект.

Построение CORBA-клиента

Действия, необходимые для проектирования клиентского приложения, обращающегося к серверу, также не сложны.

Для построения CORBA-клиента нужно запустить мастера CORBA Client командой File | New | Other | Multitier | CORBA Server (рис. 5.9).

Рисунок 9

В появившемся диалоговом окне (рис. 5.10) нужно выбрать тип приложения и ввести имя IDL-файла user.idl, описывающего объект, к которому будет обращаться CORBA-клиент (можно и не указывать этого имени, а просто добавить IDL-файл в проект).

Рисунок 10

Далее нужно спроектировать несложный интерфейс пользователя, позволяющий соединяться с CORBA-сервером (рис. 11).

Рисунок 11

#include <vcl.h>

#pragma hdrstop

#include «CORBAClientUnit.h»

#include «user_c.hh» // !!!

//—————————————————————————

#pragma package(smart_init)

#pragma resource «*.dfm»

TForm2 *Form2;

//—————————————————————————

__fastcall TForm2::TForm2(TComponent* Owner)

: TForm(Owner)

{

}

//—————————————————————————

void __fastcall TForm2::Button1Click(TObject *Sender)

{

User::Welcome_var H = User::Welcome::_bind(«WelcomeObject»);

H->Hello();

}

В обработчике нажатия на кнопку «Подключение к CORBA-серверу» помещают исходный текст, производящий вызов метода Hello() удаленного объекта WelcomeObject интерфейса Welcome модуля User.

Тестирование ИС

Для тестирования ИС следует активизировать утилиту Smart Agent из меню Tools (это программа c:Inprisevbrokerbinosagent.exe) (рис. 12).

Рисунок 12

и последовательно (вне среды C++ Builder) запустить CORBA-сервер и CORBA-клиент

Пример 2. Создание многоуровневой ИС

Рассмотрим пример создания многоуровневой ИС, в которой клиент из банкомата может обратиться к серверу банка и выполнить нужные ему операции (рис. 15).

Рисунок 15
Для ускорения обработки данных серверы банков реализованы в разных каналах.

Пример следует рассмотреть самостоятельно, руководствуясь комментариями к нижеприведенному коду программы.

Xaction.idl

enum EnumAction {

balance,

withdraw,

deposit

};

enum EnumStatus {

OK,

invalid,

complete,

incomplete

};

struct xaction {

long UserID;

long PIN;

long account;

double amount;

::EnumAction action;

double balance;

::EnumStatus status;

};

interface Server {

exception NoServer {

string message;

};

::xaction HandleTransaction(

inout ::xaction Transaction

);

/* raises(

::Server::NoServer

);

*/

long Balance();

};

banking.idl

#include «xaction.idl»

interface BankServer {

::xaction HandleTransaction(

inout ::xaction Transaction

);

long BankID();

};

module Bank {

interface Account {

float balance();

};

Читайте также:  Власть и партнерство в совместной работе

interface AccountManager {

::Bank::Account open(

in string name

);

};

};

Рисунок 16. Проект и интерфейс банкомата

Рисунок 17. Режим «Администрирование»

ATMUnit/h

//—————————————————————————

#ifndef atmunitH

#define atmunitH

//—————————————————————————

#include <Classes.hpp>

#include <Controls.hpp>

#include <StdCtrls.hpp>

#include <Forms.hpp>

#include <ExtCtrls.hpp>

#include <ComCtrls.hpp>

#include <Buttons.hpp>

//—————————————————————————

class ATMObject

{

private:

long _ID;

String _serverName;

public:

ATMObject(){_serverName = «Wells Fargo»; _ID = 100;};

ATMObject(String name){_serverName = name; _ID = 100;};

String serverName(){return _serverName;}

void serverName(String name){_serverName = name;}

long ID(){return _ID;}

void ID(long id){_ID = id;}

};

class TFormATM : public TForm

{

__published: // IDE-managed Components

TEdit *NameBox;

TEdit *PINBox;

TEdit *AmountBox;

TLabel *Label1;

TLabel *Label2;

TLabel *Label3;

TRadioGroup *Action;

TMemo *Memo1;

TRadioGroup *AccountType;

TStatusBar *StatusBar1;

TBitBtn *BitBtn1;

TBitBtn *BitBtn2;

TGroupBox *GroupBox1;

TGroupBox *GroupBox2;

TBitBtn *BitBtn3;

TLabel *Label4;

TLabel *Label5;

TBevel *Bevel1;

void __fastcall FormCreate(TObject/* */ *Sender);

void __fastcall BitBtn1Click(TObject *Sender);

void __fastcall BitBtn2Click(TObject *Sender);

void __fastcall BitBtn3Click(TObject *Sender);

private: // User declarations

public: // User declarations

__fastcall TFormATM(TComponent* Owner);

ATMObject * ATM;

long __fastcall TestConnection();

};

//—————————————————————————

extern PACKAGE TFormATM *FormATM;

//—————————————————————————

#endif

ATMUnit.cpp

#include <vcl.h>

#pragma hdrstop

#include «atmunit.h»

#include «servname.h»

#include «xaction_c.hh»

//—————————————————————————

#pragma package(smart_init)

#pragma resource «*.dfm»

USE_STD_NS

TFormATM *FormATM;

//—————————————————————————

__fastcall TFormATM::TFormATM(TComponent* Owner)

: TForm(Owner)

{

}

char * const * argV;

int argC;

//—————————————————————————

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

// Mimic streaming to VCL Memo Window

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

class catchit: public streambuf

{

TMemo * M;

int ct;

String S;

char * cbuff;

public:

catchit(TMemo *Memo){M = Memo; ct = 1;};

int sync();

int overflow(int ch);

};

int catchit::overflow(int ch)

{

S += (char)ch;

return 0;

}

int catchit::sync()

{

// M->Lines->Strings[ct++] = S;

M->Lines->Add(S);

S = «»;

return ct;

}

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

// class _update

// Instantiate this object to interface with the view

// Usage: new _update(FormATM);

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

class _update

{

private:

TFormATM * theForm;

public:

__fastcall _update(TFormATM* ATMForm)

{

theForm = ATMForm;

}

long AccountType()

{

return (long)theForm->AccountType->ItemIndex + 1;

}

EnumAction ActionType()

{

return (EnumAction)theForm->Action->ItemIndex;

}

long UserID()

{

if (theForm->NameBox->Text == «John») return 0;

if (theForm->NameBox->Text == «Bill») return 1;

if (theForm->NameBox->Text == «Jim») return 2;

if (theForm->NameBox->Text == «Gene») return 3;

if (theForm->NameBox->Text == «Wally») return 4;

if (theForm->NameBox->Text == «Frank») return 5;

return -1; // неизвестный пользователь

}

long PIN()

{ try {

return (long)theForm->PINBox->Text.ToInt();

} catch (Exception &e) {

return (long)0;

}

}

double Amount()

{

return theForm->AmountBox->Text.ToDouble();

}

void UpdateList()

{ theForm->Memo1->Lines->Clear();

theForm->Memo1->Lines->Add(«John, PIN:123, Bank 1″);

theForm->Memo1->Lines->Add(«Bill, PIN:456, Bank 1″);

theForm->Memo1->Lines->Add(«Jim, PIN:789, Bank 1″);

theForm->Memo1->Lines->Add(«Gene, PIN:123, Bank 2″);

theForm->Memo1->Lines->Add(«Wally, PIN:456, Bank 2″);

theForm->Memo1->Lines->Add(«Frank, PIN:789, Bank 2″);

}

void UpdateMemo(String str)

{

theForm->Memo1->Lines->Add(str);

}

void UpdateStatus(String str)

{

theForm->StatusBar1->SimpleText = str;

}

void Clear()

{

theForm->Memo1->Clear();

}

};

#define mrOK 1

long __fastcall TFormATM::TestConnection()

{ // проверка соединения

try {

CORBA::ORB_ptr orb = CORBA::ORB_init();

Server_ptr S = Server::_bind(ServerNameDlg->ServerNameEdit->Text.c_str());

return S->Balance();

} catch(CORBA::Exception &e) {

return 0;

}

}

//—————————————————————————

void __fastcall TFormATM::FormCreate(TObject *Sender)

{

ATM = new ATMObject();

}

//—————————————————————————

void __fastcall TFormATM::BitBtn1Click(TObject *Sender)

{ // Администрирование

if (ServerNameDlg->ShowModal() == mrOK) {

ATM->serverName(ServerNameDlg->ServerNameEdit->Text);

}

}

//—————————————————————————

void __fastcall TFormATM::BitBtn2Click(TObject *Sender)

{ // Список клиентов

_update * U = new _update(FormATM);

U->UpdateList();

delete U;

}

//—————————————————————————

void __fastcall TFormATM::BitBtn3Click(TObject *Sender)

{ // Выполнение операции

catchit cbuf(Memo1);

ostream CCout(&cbuf); // Visibroker имеет предопределенный Cout

// Создание интерфейса просмотра ATM-объекта

_update* Input = new _update(FormATM);

// Создание объекта транзакции

xaction_var X = new xaction;

// «Заселение» объекта транзакции

X->UserID = Input->UserID();

try {

X->PIN = Input->PIN();

} catch (Exception &e) {

X->PIN = 0;

}

X->amount = Input->Amount();

X->action = Input->ActionType();

X->account = Input->AccountType();

X->balance = 0.00;

X->status = incomplete;

try {

// Старт ORB

CORBA::ORB_ptr orb = CORBA::ORB_init();

Input->UpdateStatus(«* ORB Инициализирован.»);

// Присоединение к ATM-серверу

Server_ptr ATMServer = Server::_bind(ATM->serverName().c_str());

Input->UpdateStatus(«Присоединение к ATM-серверу завершено.»);

Input->UpdateStatus(«ATM-сервер открыт.»);

// Передача транзакции ATM-серверу

ATMServer->HandleTransaction(X);

if (X->status == complete) {

Input->UpdateMemo(«Баланс счёта: $» + CurrToStr(X->balance));

Input->UpdateMemo(«Транзакция завершена.»);

} else if (X->status == incomplete) {

Input->UpdateMemo(«Транзакция не обработана.»);

Input->UpdateMemo(«Баланс счёта: $» + CurrToStr(X->balance));

} else if (X->status == invalid) {

Input->Clear();

Input->UpdateMemo(«* ID клиента и PIN не найдены!»);

}

}

catch(const CORBA::Exception& e) {

CCout << e._name() << endl;

Input->UpdateStatus(«* ATM-сервер отключен!»);

}

}

//—————————————————————————

Servername.h

//—————————————————————————-

#ifndef servnameH

#define servnameH

//—————————————————————————-

#include <vclSystem.hpp>

#include <vclWindows.hpp>

#include <vclSysUtils.hpp>

#include <vclClasses.hpp>

#include <vclGraphics.hpp>

#include <vclStdCtrls.hpp>

#include <vclForms.hpp>

#include <vclControls.hpp>

#include <vclButtons.hpp>

#include <vclExtCtrls.hpp>

//—————————————————————————-

class TServerNameDlg : public TForm

{

__published:

TButton *OKBtn;

TButton *CancelBtn;

TBevel *Bevel1;

TLabel *Label1;

TLabel *ServerNameLabel;

TEdit *ServerNameEdit;

TLabel *Label2;

TButton *ConnectButton;

TLabel *Label3;

TLabel *CountLabel;

TLabel *ResultLabel;

void __fastcall FormShow(TObject/* */ *Sender);

void __fastcall ConnectButtonClick(TObject/* */ *Sender);

void __fastcall OKBtnClick(TObject/* */ *Sender);

private:

public:

virtual __fastcall TServerNameDlg(TComponent* AOwner);

};

//—————————————————————————-

extern PACKAGE TServerNameDlg *ServerNameDlg;

//—————————————————————————-

#endif

Servername.cpp

#include <vcl.h>

#pragma hdrstop

#include «servname.h»

#include «atmunit.h»

//———————————————————————

#pragma resource «*.dfm»

TServerNameDlg *ServerNameDlg;

//———————————————————————

__fastcall TServerNameDlg::TServerNameDlg(TComponent* AOwner)

: TForm(AOwner)

{

}

//———————————————————————

void __fastcall TServerNameDlg::FormShow(TObject/* */ *Sender)

{

ServerNameLabel->Caption = FormATM->ATM->serverName();

ServerNameEdit->Text = ServerNameLabel->Caption;

ResultLabel->Caption = «»;

}

//—————————————————————————

void __fastcall TServerNameDlg::ConnectButtonClick(TObject/* */ *Sender)

{

CountLabel->Caption = String(FormATM->TestConnection());

if (CountLabel->Caption == «0»)

ResultLabel->Caption = «* Соединения нет!»;

else

ResultLabel->Caption = «Соединение установлено.»;

}

//—————————————————————————

void __fastcall TServerNameDlg::OKBtnClick(TObject/* */ *Sender)

{

if (CountLabel->Caption != String(«0»)) {

FormATM->ATM->serverName(ServerNameEdit->Text);

}

}

//—————————————————————————

Рисунок 5.18. Проект и интерфейс ATM-сервера

#ifndef atmserverunitH

#define atmserverunitH

//—————————————————————————

#include <Classes.hpp>

#include <Controls.hpp>

#include <StdCtrls.hpp>

#include <Forms.hpp>

#include «xaction_s.hh»

#include «banking_s.hh»

#include <Buttons.hpp>

//—————————————————————————

class TForm2 : public TForm

{

__published: // IDE-managed Components

TLabel *Transactions;

TEdit *Count;

TEdit *ServerNameEdit;

TLabel *Label1;

TBitBtn *BitBtn1;

TGroupBox *GroupBox2;

TGroupBox *GroupBox1;

TBitBtn *BitBtn2;

TMemo *Memo1;

TComboBox *BankBox;

void __fastcall FormClose(TObject *Sender, TCloseAction &Action);

void __fastcall BitBtn1Click(TObject *Sender);

void __fastcall BitBtn2Click(TObject *Sender);

private: // User declarations

public: // User declarations

__fastcall TForm2(TComponent* Owner);

void StartServer();

void DownServer();

CORBA::ORB_var orb;

CORBA::BOA_var boa;

CORBA::Object_ptr obj;

String CurrentServerName;

};

//—————————————————————————

extern PACKAGE TForm2 *Form2;

//—————————————————————————

#endif

ATMServerUnit.cpp

#include <vcl.h>

#pragma hdrstop

#include «atmserverunit.h»

//—————————————————————————

#pragma package(smart_init)

#pragma resource «*.dfm»

TForm2 *Form2;

//—————————————————————————

__fastcall TForm2::TForm2(TComponent* Owner)

: TForm(Owner)

{

}

//—————————————————————————

char * const * argV;

int argC;

//—————————————————————————

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

// Implement CORBA object from skeleton class

Читайте также:  Литография: истоки и современность

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

class ATMServerImpl : public _sk_Server

{

public:

ATMServerImpl(const char *object_name);

void UpCount(int i = 0){

if (i == 1) {

Form2->Memo1->Lines->Add(«ATM-сервер включен.»);

return;

}

Form2->Count->Text = String(count++);

}

virtual xaction HandleTransaction(xaction& Transaction)

{

UpCount();

Form2->Memo1->Lines->Add(«Банк найден.»);

Transaction.status = invalid;

for (int i = 0; i < UserCount; i++) {

if(Transaction.UserID == CardHolders[i]->UserID) {

if (Transaction.PIN == CardHolders[i]->PIN) {

Transaction.status = OK;

try {

BankServer_var BankServer = BankServer::_bind((*Banks[CardHolders[i]->Bank]).c_str());

BankServer->HandleTransaction(Transaction);

Form2->Memo1->Lines->Add(«Транзакция с » + *Banks[CardHolders[i]->Bank]);

} catch(CORBA::Exception &e){

Form2->Memo1->Lines->Add(«* Сервер банка недоступен!»);

return Transaction;

}

}

}

}

// Transaction.status = complete;

return Transaction;

}

virtual CORBA::Long Balance(){UpCount(); return CORBA::Long(count);}

class NoServer: public CORBA::UserException

{

public:

NoServer(){}

static ATMServerImpl::NoServer* _narrow() throw (CORBA::SystemException);

};

private:

int count;

struct _user{

long UserID;

long Bank;

long PIN;

};

_user * CardHolders[10];

long BankOne;

long BankTwo;

int UserCount;

String * Banks[10];

};

ATMServerImpl::ATMServerImpl(const char *object_name=NULL) :

_sk_Server(object_name)

{

count = 0;

UserCount = 0;

UpCount(1);

Banks[0] = new String(«BankOne»);

Banks[1] = new String(«BankTwo»);

TStrings *SL = new TStringList();

SL->Add(*Banks[0]);

SL->Add(*Banks[1]);

Form2->BankBox->Items->Assign(SL);

Form2->BankBox->ItemIndex = 0;

BankOne = 0;

BankTwo = 1;

CardHolders[0] = new _user;

CardHolders[1] = new _user;

CardHolders[2] = new _user;

CardHolders[3] = new _user;

CardHolders[4] = new _user;

CardHolders[5] = new _user;

// user 1

CardHolders[0]->UserID = 0; // «John»;

CardHolders[0]->PIN = 123;

CardHolders[0]->Bank = BankOne;

UserCount++;

CardHolders[1]->UserID = 1; // «Bill»;

CardHolders[1]->PIN = 456;

CardHolders[1]->Bank = BankOne;

UserCount++;

CardHolders[2]->UserID = 2; // «Jim»;

CardHolders[2]->PIN = 789;

CardHolders[2]->Bank = BankOne;

UserCount++;

CardHolders[3]->UserID = 3; // «John»;

CardHolders[3]->PIN = 123;

CardHolders[3]->Bank = BankTwo;

UserCount++;

CardHolders[4]->UserID = 4; // «Bill»;

CardHolders[4]->PIN = 456;

CardHolders[4]->Bank = BankTwo;

UserCount++;

CardHolders[5]->UserID = 5; // «Jim»;

CardHolders[5]->PIN = 789;

CardHolders[5]->Bank = BankTwo;

UserCount++;

}

ATMServerImpl* ATMServer;

void TForm2::StartServer()

{

try {

// Инициализация ORB и BOA

orb = CORBA::ORB_init(argC, argV);

boa = orb->BOA_init(argC, argV);

if (obj) {

Form2->Memo1->Lines->Add(«* ATM-сервер уже активен!»);

ServerNameEdit->Text = CurrentServerName;

} else {

// Создание нового серверного объекта

obj = new ATMServerImpl(ServerNameEdit->Text.c_str()); //»Wells Fargo»);

CurrentServerName = ServerNameEdit->Text;

// Экспорт созданного объекта

boa->obj_is_ready(obj);

// Ожидание приходящих запросов

// boa->impl_is_ready();

}

} catch(const CORBA::Exception& e) {

ShowMessage(«* Перехвачено CORBA-исключение!»);

}

}

void TForm2::DownServer()

{

try {

if (obj) {

boa->deactivate_obj(obj);

obj->_release();

obj = obj->_nil();

}

Form2->Memo1->Lines->Add(«* ATM-сервер отключен!»);

} catch(CORBA::Exception &e){

ShowMessage(«* Проблема при отключении ATM-сервера!»);

}

}

//—————————————————————————

class ServerThread : public TThread

{

public:

__fastcall ServerThread(bool CS):TThread(CS){};

void __fastcall Execute()

{

try {

// Инициализвция ORB и BOA

CORBA::ORB_var orb = CORBA::ORB_init(argC, argV);

CORBA::BOA_var boa = orb->BOA_init(argC, argV);

// Создание нового серверного объекта

ATMServerImpl ATMServerWells Fargo«);

// Экспорт созданного объекта

boa->obj_is_ready(&ATMServer);

// Ожидание приходящих запросов

boa->impl_is_ready();

} catch(const CORBA::Exception& e) {

ShowMessage(«* Перехвачено CORBA-исключение!»);

}

}

};

ServerThread * ST;

//—————————————————————————

void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)

{ // отключение сервера

BitBtn1->Caption = «Включение AYM-сервера»;

DownServer();

}

//—————————————————————————

void __fastcall TForm2::BitBtn1Click(TObject *Sender)

{ // включение/отключение ATM-сервера

static bool ServerStarted = false;

if (!ServerStarted) { // включение сервера

Form2->Height = 237;

BitBtn1->Caption = «Отключение ATM-сервера»;

// ST = new ServerThread(false);

StartServer();

} else { // отключение сервера

Form2->Height = 108;

BitBtn1->Caption = «Включение ATM-сервера»;

DownServer();

}

ServerStarted = !ServerStarted;

}

//—————————————————————————

void __fastcall TForm2::BitBtn2Click(TObject *Sender)

{ // подключение к серверу выбранного в списке банка

try { // попытка подключения к серверу выбранного в списке банка

BankServer_ptr BankServer =

BankServer::_bind(Form2->BankBox->Items->Strings[BankBox->ItemIndex].c_str());

// занесение ID банка в Memo

long ID = BankServer->BankID();

Form2->Memo1->Lines->Add(

AnsiString («Банк «) +

(ID == 800 ? AnsiString(«BankTwo») : AnsiString(«BankOne»)) +

AnsiString(» подключен.»));

} catch(CORBA::Exception &e){

ShowMessage(e._name());

}

}

Рисунок 5.19. Проект и интерфейс BankServerOne

#ifndef BankUnitOneH

#define BankUnitOneH

//—————————————————————————

#include <Classes.hpp>

#include <Controls.hpp>

#include <StdCtrls.hpp>

#include <Forms.hpp>

#include <Buttons.hpp>

#include <ComCtrls.hpp>

//—————————————————————————

class TBankOneForm : public TForm

{

__published: // IDE-managed Components

TEdit *CountBox;

TLabel *Label1;

TMemo *Memo1;

TBitBtn *BitBtn1;

TStatusBar *StatusBar1;

void __fastcall BitBtn1Click(TObject *Sender);

private: // User declarations

public: // User declarations

__fastcall TBankOneForm(TComponent* Owner);

};

//—————————————————————————

extern PACKAGE TBankOneForm *BankOneForm;

//—————————————————————————

#endif

BankUnitOne.cpp

//—————————————————————————

#include <vcl.h>

#pragma hdrstop

#include «BankUnitOne.h»

#include «banking_s.hh»

//—————————————————————————

#pragma package(smart_init)

#pragma resource «*.dfm»

AnsiString Accounts [] = {«Проверка», «Кредит»};

AnsiString Operations [] = {«Баланс», «Снять», «Внести»};

TBankOneForm *BankOneForm;

//—————————————————————————

__fastcall TBankOneForm::TBankOneForm(TComponent* Owner)

: TForm(Owner)

{

}

//—————————————————————————

char * const * argV;

int argC;

//—————————————————————————

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

// Implement CORBA object from skeleton class

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

class BankServerImpl : public _sk_BankServer

{

public:

BankServerImpl(const char *object_name);

void UpCount(int i = 0) {

if (i == 1) {

BankOneForm->StatusBar1->SimpleText = «Сервер включен»;

return;

}

BankOneForm->CountBox->Text = String(++count);

}

virtual long BankID()

{

return BankNumber;

}

virtual xaction HandleTransaction(xaction& Transaction)

{

bool PostChange = false;

double workingBalance = 0;

UpCount();

Transaction.status = incomplete;

BankOneForm->Memo1->Lines->Add(«ID клиента: » + String(Transaction.UserID));

BankOneForm->Memo1->Lines->Add(«Счет: « + Accounts[Transaction.account]);

BankOneForm->Memo1->Lines->Add(«Операция: « + Operations[Transaction.action]);

for (int i = 0; i < UserCount; i++) {

if (Transaction.UserID == Customers[i]->UserID) {

if (Transaction.account == 1)

workingBalance = Customers[i]->AccountChecking;

else

workingBalance = Customers[i]->AccountSavings;

switch (Transaction.action) {

case balance:

Transaction.balance = workingBalance;

Transaction.status = complete;

break;

case withdraw:

Transaction.balance = workingBalance;

workingBalance -= Transaction.amount;

if (workingBalance < 0) {

Transaction.status = incomplete;

} else {

Transaction.balance = workingBalance;

Transaction.status = complete;

PostChange = true;

}

break;

case deposit:

workingBalance += Transaction.amount;

Transaction.balance = workingBalance;

Transaction.status = complete;

PostChange = true;

break;

}

if (PostChange) {

if (Transaction.account == 1)

Customers[i]->AccountChecking = workingBalance;

else

Customers[i]->AccountSavings = workingBalance;

}

}

}

return Transaction;

}

private:

long BankNumber;

int count;

int UserCount;

struct _user{

long UserID;

double AccountChecking;

double AccountSavings;

};

_user * Customers[10];

};

BankServerImpl::BankServerImpl(const char *object_name = NULL):

_sk_BankServer(object_name)

{

BankNumber = 900;

count = 0;

UserCount = 0;

Customers[0] = new _user;

Customers[1] = new _user;

Customers[2] = new _user;

Customers[0]->UserID = 0; // «John»

Customers[0]->AccountChecking = 2000.00;

Customers[0]->AccountSavings = 90.00;

UserCount++;

Customers[1]->UserID = 1; // Bill;

Customers[1]->AccountChecking = 100.00;

Customers[1]->AccountSavings = 500.00;

UserCount++;

Customers[2]->UserID = 2; // Jim;

Customers[2]->AccountChecking = 1000.00;

Customers[2]->AccountSavings = 5000.00;

UserCount++;

}

//—————————————————————————

class ServerThread : public TThread

{

public:

__fastcall ServerThread(bool CS):TThread(CS){};

void __fastcall Execute()

{

try {

// Инициализация ОRB и BOA

CORBA::ORB_var orb = CORBA::ORB_init(argC, argV);

CORBA::BOA_var boa = orb->BOA_init(argC, argV);

// Создание нового серверного объекта

BankServerImpl BankServerBankOne«);

// Экспорт сервероного объекта

boa->obj_is_ready(&BankServer);

BankOneForm->StatusBar1->SimpleText = «Сервер включен»;

// Ожидание приходящих запросов

boa->impl_is_ready();

} catch(const CORBA::Exception& e) {

ShowMessage(«* Перехвачено CORBA-исключение!»);

}

}

};

ServerThread * ST;

//—————————————————————————

void __fastcall TBankOneForm::BitBtn1Click(TObject *Sender)

{ static bool Switch = false;

Switch = !Switch;

BitBtn1->Caption = «Отключение сервера банка»;

if (Switch) ST = new ServerThread(false);

else Close();

}

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...