Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Самостійна робота № 19
Тема: Створення серверів та клієнтів DСОМ
1. Реалізація внутрішнього сервера СОМ і його клієнта
2. Реалізація і використання локальних серверів DСОМ
3. Створення клієнтського застосування для сервера
1. Архангельській А.Я. Програмування в C++ Builder 6. - М.: Біном, 2003, 486-495с.
Теоретичні положення
Гідність технології DСОМ в тому, що вона не залежить від мови. Якщо на комп'ютері є якісь інші системи, підтримуючі DCOM (Delphi, Visual Basic і тому подібне), то можна, наприклад, реалізувати з їх допомогою сервер, і створене в C++Builder клієнтське застосування без проблем працюватиме з ним. Або навпаки, клієнти, реалізовані в будь-якій іншій системі програмування, зможуть працювати з сервером, реалізованим за допомогою C++Builder.
Хай цей сервер міститиме вікно редагування, в яке можна заносити якийсь текст повідомлення. А клієнти сервера зможуть читати це повідомлення і заносити на сервер власні повідомлення. Таким чином, клієнти зможуть спілкуватися один з одним. Треба додати на сервер метод, який по запиту клієнта може управляти видимістю сервера.
Завдання до cамостійної роботи № 16
1. Почати нове застосування, перенести на форму вікно редагування Edit і задати заголовок форми «Сервер MyServer».
2. Зберегти проект під ім'ям за умовчанням «Project1». Це ім'я буде у виконуваного файлу сервера.
3. Тепер треба перетворити звичайний проект C++Builder на локальний сервер DСОМ. Виконати команду File | New | Other і на сторінці ACTIVEX Депозитарію вибрати піктограму Automation Object об'єкт автоматизації. У діалоговому вікні, яке відкриється CaClass Name вказати ім'я класу «MyObject».
4. У вікні Редактора Бібліотеки Типів внести до інтерфейсу ім'я цього інтерфейсу «IMyServer», клас його батьківського інтерфейсу треба встановити рівним IDispatch. Перш за все, ввести в цей інтерфейс метод SetVis. Цей метод управлятиме видимістю сервера. Задати в методі один параметр з ім'ям Vis, типом VARIANT_BOOL (це булевий тип, використовуваний в DСОМ) і специфікатором [in]. Цей параметр указуватиме, чи повинен сервер бути видимим (при значенні true) або невидимим (при значенні false).
5. Ввести в інтерфейс властивість з ім'ям Mess. Воно представлятиме читаний або записуваний текст сервера. Натиснути кнопочку випадного списку поряд з кнопкою Property. Відкриється меню з розділами Read | Write (для читання і запису), Read Only (тільки для читання), Write Only (тільки для запису), Read | Write | Write By Ref (для читання, запису і запису по посиланню). Оскільки треба і читати, і записувати значення Mess слід вибрати розділ Read | Write. В результаті в лівій панелі Редактора Бібліотеки Типів з'являться дві вершини: одна для функції запису, інша для функції читання. Задати одній з них ім'я «Mess». Це ж ім'я автоматично привласниться і другій вершині. На сторінці Attributes задати тип властивості BSTR. Це тип рядків, використовуваний в DСОМ.
6. Для функції читання на сторінці Parameters задайте ім'я параметра функції «Text», тип параметра «BSTR *» покажчик на BSTR, специфікатор параметра «[out, retval]». Для функції запису ім'я параметра «Text», тип параметра «BSTR», специфікатор параметра «[in]». Повертаний тип в обох функціях HRESULT.
7. Формування властивостей і методів інтерфейсу закінчене. Тепер можна їх реалізовувати. Клацнути на кнопці Refresh Implementation (Відновити реалізацію). Перейти в Редактор Коди. У файлі MyServeImpl.cpp будуть заготовки функцій запису і читання get_Mess, set_Mess і методу SetVis. Додати по одному операторові в кожну з цих заготовок. В результаті вони повинні виглядати так:
STDMETHODIMP TMyServerlmpl::getJMess(BSTR* Text)
{
try
*Text = WideString((Forml->Editl->Text).c_str()).c_bstr0;}
catch(Exception Se)
{ return Error(e.Message.c_str(), IID_IMyServer); }
return S_OK; };
STDMETHODIMP TMyServerlmpl::set_Mess(BSTR Text)
{
try
Forml->Editl->Text = Text; }
catch(Exception Se)
{ return Error(e.Message.c_str(}, IID_IMyServer);}
return S_OK; };
STDMETHODIMP TMyServerlmpl::SetVis(VARIANT_BOOL Vis)
{
Forml->Visible = Vis;
return S_OK;
}
8. Дія функції set_Mess очевидено: у вікно Edit1 записується текст, переданий у функцію як параметр Text. Реалізація функції SetVis також очевидна: видимість форми встановлюється рівною переданому у функцію булеву параметру Vis. Реалізація функції get_Mess наступна. Треба занести в переданий по посиланню параметр текст, що міститься у вікні Edit1. Цей текст має тип AnsiString, а треба перетворити його в тип BSTR. Приведеного оператора здійснює це перетворення таким чином. Спочатку за допомогою c_str() функції-елементу класу AnsiString текст перетворюється в тип char *. Потім результат перетворення передається в конструктор класу WideString. В результаті виходить рядок символів Unicode. І, нарешті, за допомогою c_bstr() функції-елементу класу WideString рядок перетворюється в тип BSTR.
9. Проектування сервера закінчене. Зберегти проект, відкомпілювати і виконати. У момент запуску сервер автоматично реєструватиметься в системі: у реєстр Windows запишуться його ідентифікатори і місце розміщення файлу.
10. Тепер можна реалізовувати клієнтське застосування. Почати новий проект і створити форму.
Кнопка Прийняти (BGetMess) повинна забезпечувати відображення у вікні редагування Edit1 текст повідомлення, записаного на сервері. Кнопка Поспати (BSetMess) повинна забезпечувати передачу тексту з вікна редагування на сервер. Кнопка Видимість (BSetVis) повинна управляти видимістю сервера залежно від стану індикатора Видимий (CheckBoxl). Нижче приведений варіант коду клієнтського застосування.
Variant Serv;
void__fastcall TForm1::FormCreate(TObjeot *Sender)
{ Serv = CreateOleObject("Projectl.MyServer"); }
//
void__fastcall TForml::BGetMessClick(TObject *Sender)
{ Editl->Text = Serv.OlePropertyGet("Mess") ; }
//
void__fastcall TForml :: BSetMessClick (TObject *Sender)
{ Serv.OlePropertySet("Mess"
WideString((Editl->Text).c_str()).c_bstr());
//
void__fastcall TForml::BSetVisClick(TObject «Sender)
{ Serv.OleProcedure("Setvis", CheckBox1->Checked); }
У додатку вводиться глобальна змінна Serv об'єкт сервера. Тип цієї змінної Variant. Перша процедура приведеної коди FormCreate є обробником події OnCreate форми. У цій процедурі функцією CreateOleObject в Serv створюється об'єкт OLE інтерфейсу, по якому можна зв'язуватися з сервером. Ім'я сервера і його об'єкту передається в CreateOleObject як параметр. Всі необхідні операції по зв'язку з сервером виконуються автоматично. Якщо в даний момент сервер не виконується, він буде запущений на виконання. Якщо ж сервер вже працює, то з ним буде встановлений зв'язок.
Функція BgetMessClick читає повідомлення з сервера у вікно Editl. Для доступу до значення властивості Mess використовується функція OlePropertyGet. Як параметр в неї передається рядок з ім'ям читаної властивості. Функція BSetMessCIick посилає на сервер у властивість Mess текст з вікна Edit1. Робиться це за допомогою функції OlePropertySet. Першим параметром в цю функцію передається рядок з ім'ям властивості, значення якої треба встановити. Другим параметром передається встановлюване значення. В даному випадку здійснюється перетворення типу AnsiString в тип BSTR.
Функція BSetVisClick виконує метод SetVis сервера. Для виконання методу використовується функція OleProcednre. Як перший параметр в неї передається рядок з ім'ям методу, що викликається. А подальші параметри містять значення параметрів методу. В даному прикладі треба передати тільки один параметр булеву величину CheckBoxl->Checked, вказуючу, чи повинен сервер бути видимим, чи ні.
11. Зберегти проект і виконати його. При цьому автоматично запуститься сервер, і клієнт зможе їм управляти: заносити в нього свої повідомлення, приймати повідомлення, записані у вікні сервера, встановлювати видимість сервера. Як тільки закриється клієнтське застосування, сервер теж завершить роботу.
12. Щоб повністю з'ясувати взаємодію сервера і клієнтів треба запустити засобами Windows декілька екземплярів клієнтських застосувань. Всі вони працюють з одним екземпляром сервера і можуть обмінюватися через нього повідомленнями. Якщо закрити один екземпляр клієнта, сервер продовжить роботу. Його робота завершиться тільки після того, як буде закритий останній клієнт.
13. Експеримент, який покаже, як реєструється сервер. Перенести засобами Windows виконуваний файл сервера Projec1l.exe у якійсь інший каталог. При спробі виконати клієнтське застосування буде видано повідомлення про помилку: «Не вдається знайти вказаний файл». Це тому, що в реєстрі записаний каталог, в якому повинен знаходитися сервер, а зараз в цьому каталозі потрібного файлу немає. Але достатньо один раз виконати додаток сервера з нового каталога, і його працездатність відновиться. Сервер знову реєструватиметься в системі і тепер клієнти, розташовані в будь-яких каталогах, зможуть з ним зв'язуватися.
Цей експеримент показав не тільки особливості реєстрації сервера, але і певні недоліки клієнтського застосування. Воно не застраховане від збоїв. Один із збоїв вийшов при спробі запустити незареєстрований або неправильно зареєстрований сервер. Інший збій наступить, якщо клієнт пов'язаний з сервером, а в цей час хтось цей сервер закрив. Правда, при спробі закрити сервер з'явиться вікно з попередженням англійською мовою, що ще є клієнти, що працюють з даним сервером, і закриття сервера порушить їх роботу. Але якщо, не дивлячись на це попередження, закрити сервер, то при подальшому зверненні клієнта до його властивостей і методів вийде повідомлення про помилку: «Сервер RPC недоступний».
14. Бажано передбачити в клієнтському застосуванні обробку відповідних виключень. Нижче приведений виправлений код з розглянутих раніше функцій. Останні слід оформляти аналогічним чином.
void__fastcall TForm1::FormCreate(TObject *Sender)
{
try
{ Serv=Create0leObject("Projectl.MyServer"); }
catch(Exception S)
{ ShowMessage("He вдалося з'єднатися з сервером 'Projectl.MyServer'"); }
void __fastcall TForml::BGetMessClick(TObject *Sender)
{
try
{ Edit1->Text = Serv.OlePropertyGet("Mess"); }
catch(Exception &)
{ShowMessage("Сервер'Projectl.MyServer'недоступний");}
}