Архив номеров
Форум
Контакты

Каркасы ACE

ЭТИМ МАТЕРИАЛОМ МЫ ЗАВЕРШАЕМ ЦИКЛ СТАТЕЙ, ПОСВЯЩЕННЫХ БИБЛИОТЕКЕ ACE. В ПРЕДЫДУЩИХ СТАТЬЯХ МЫ РАССМОТРЕЛИ ВОЗМОЖНОСТИ БИБЛИОТЕКИ, ПОЗВОЛЯЮЩИЕ СОЗДАВАТЬ ПЕРЕНОСИМЫЕ СЕТЕВЫЕ ПРИЛОЖЕНИЯ БЕЗ ИСПОЛЬЗОВАНИЯ ПЛАТФОРМОЗАВИСИМЫХ API.

Теперь я расскажу вам о наиболее сильной стороне ACE, а именно - о каркасах приложений, которые позволяют сэкономить программистам массу времени при разработке событийно-управляемой архитектуры приложения и организации клиент-серверного взаимодействия.

Что такое каркас?

Итак, что же такое каркас приложения? Это набор классов, занимающихся диспетчеризацией событий и регистрацией их источников. Каждый такой класс определяет виртуальные методы, которые должны быть реализованы программистом. С помощью этих реализаций программист определяет реакцию своей программы на произошедшие события. Отличными примерами каркасов являются классы библиотек графических интерфейсов MFC, wxWidgets, QT и GTK+. Эти классы, реализующие такие сущности пользовательского интерфейса, как окна, меню, кнопки и т.д., предоставляют программисту некий стек решений для создания утилиты. Для каждого класса, например диалогового окна, можно перегрузить методы, определяющие реакцию программы на нажатие кнопки мыши или клавиатуры. Каркасы ACE используют аналогичный подход, позволяя программисту задать реакцию программы на произошедшее событие.

Основная идея

Заключается она в том, что для организации реакции приложения на поступающие клиентские запросы, прерывания, ввод/вывод и т.д. используются обработчики событий/прерываний. Диспетчеризация этих обработчиков происходит различными средствами операционной системы, следовательно, результирующий код непереносим, является кладезем случайных ошибок и вряд ли может быть использован повторно. В свою очередь, каркасы ACE предоставляют готовые решения и наборы правил игры, которых должны придерживаться разработчики. Это готовый и неоднократно проверенный код, который сопровождается хорошей документацией, примерами и, что немаловажно, тестами, которые могут однозначно подтвердить работоспособность кода ACE на целевой платформе.

Обработчики событий

Для формирования реакции утилиты на происходящие события программисты должны реализовывать класс-обработчик, производный от класса ACE_Event_Handler. Этот класс предусматривает различные обработчики для следующих типов событий: события ввода, события вывода, исключительные события, события таймера, события сигналов операционной системы, события закрытия обработчика. При регистрации обработчика мы должны явно указать необходимые нам маски событий, на которые он будет реагировать. Маски можно комбинировать между собой с помощью оператора «ИЛИ». Маска READ_MASK используется, когда требуется обработать события ввода. Это может быть поступление данных на сокет или в файл. Для этой маски будет вызван метод обработчика handle_input(). Маска WRITE_MASK используется для событий вывода, например, окончания передачи данных. Для этой маски механизмом диспетчеризации вызывается метод handle_output(). Маска EXCEPT_MASK применяется в тех случаях, когда происходят исключительные события, такие как поступление urgent-данных на сокет. Соответственно, механизм диспетчеризации вызовет обработчик handler_exception(). Маска ACCEPT_MASK используется для событий, связанных с пассивным приемом TCP-соединений, и при наступлении таких событий вызывается метод обработчика handle_input(). Маска TIMER_MASK применяется для обработки событий таймеров, при наступлении которых вызывается метод handle_timeout(). Маска SIGNAL_MASK используется для обработки событий, связанных с сигналами операционной системы. В этом случае механизм диспетчеризации вызовет метод обработчика handle_signal(). В качестве примера мы реализуем обработчик, который будет выводить в консоль текущее системное время при поступлении события от таймера.

#include <ace/Event_Handler.h>
#include <ace/ACE_OS.h>

class TimerHandler : public ACE_Event_Handler
{
public:
//Это важно, конструктор обработчика
//должен принимать указатель на реактор,
//чтобы передать его базовому классу
TimerHandler( ACE_Reactor *reactor ) :
ACE_Event_Handler(reactor )
{}

//Обработчик события таймера
virtual int handle_timeout(
const ACE_Time_Value & tv,
const void * act )
{
struct tm res;
ACE_OS::gmtime_r(&tv.sec(), &res);
char timestamp[MAX_TIMESTAMP_LEN];
ACE_OS::strftime(timestamp,
MAX_TIMESTAMP_LEN,
"%Y%m%d%H%M%S",
Res );
ACE_OS::printf( "Current time is %s ",
timestamp );
//См. врезку про возвращаемое значение
return 0;
}

//Обработчик события закрытия
virtual int handle_close(
ACE_HANDLE handle,
ACE_Reactor_Mask close_mask )
{
//Обработчик нам больше не нужен,
//он сам может позаботиться о себе
delete this;
return 0;
}
}

Возвращаемое обработчиком значение

Как видно из интерфейса обработчика события, он должен возвращать целочисленное число. Существует следующее правило, которому должен подчиняться обработчик. Если возвращаемое значение равно 0, то это обозначает, что реагирующий объект должен продолжать диспетчеризацию событий. Если возвращаемое значение больше 0, то диспетчеризация продолжится до момента блокировки реагирующего объекта своим демультиплексором событий. Эта возможность используется при работе с несколькими обработчиками. Если возвращаемое значение равно -1, то реагирующий объект должен прекратить диспетчеризацию событий и вызвать метод обработчика handle_close(). Важно понимать, что если обработчик зарегистрирован сразу для нескольких типов событий, то реагирующий объект прекратит слежение только за тем типом событий, для которых был вызван обработчик, вернувший -1.

Каркас ACE_Reactor

Обычно, при разработке механизма диспетчеризации событий программисты используют платформозависимые системные API или библиотеку сокетов, а именно - метод select(), следящий за изменениями в сокетных или файловых дескрипторах. Каркас ACE_Reactor позволяет создать легко масштабируемый и переносимый код механизма диспетчеризации. События могут исходить от различных источников, таких как события ввода/вывода (IPC, POSIX и Win32 сигналы), таймеры, сигналы. Каркас ACE_Reactor осуществляет диспетчеризацию событий и вызов пользовательских обработчиков. Интерфейс класса позволяет регистрировать классы-обработчики, которые должны реализовать соответствующие виртуальные методы класса ACE_Event_Handler, описанного выше. Класс ACE_Reactor реализован как класс синглтон, и его экземпляр можно получать с помощью метода instance(). Но, как и для многих синглтонов из библиотеки ACE, экземпляры реактора можно создавать явно, имея несколько реакторов для каждого из потоков в одном процессе. Некоторые реализации реактора, такие как ACE_Select_Reactor, вводят свои ограничения на использование реактора сразу для нескольких потоков. Поэтому программист должен обращать внимание на потокобезопасность используемого реактора. После инициализации реактора поток-владелец должен передать управление механизму диспетчеризации реактора. Делается это с помощью итеративных вызовов метода реактора handle_events(), либо полной передачей выполнения в метод run_reactor_event_loop(). Логично предположить, что все вызовы пользовательских обработчиков происходят в контексте потока, который передал управление механизму диспетчеризации реактора. Реализуем код, инициализирующий реактор для вызова пользовательского обработчика через определенные временные интервалы.

#include <ace/Reactor.h>

ACE_Reactor reactor;
//Интервал 10 секунд
ACE_Time_Value delay(
10, 0);
//Регистрируем обработчик
//для вызовов через каждые 10 сек.
int timerID;
timerID = reactor.schedule_timer(
new TimerHandler( &reactor ),
NULL, delay, delay );
//Итерируемся до тех пор,
//пока кто-нибудь не потребует
//закрытия этого потока
while( !close )
{
//Передаем управление
//механизму диспетчеризации
reactor.handle_events();
}
//Запрещаем дальнейшую работу
//таймера
reactor.cancel_timer(
timerID, 0, 0 );
//Последний 0 в этом вызове
//означает, что надо вызвать
//метод handle_close()
//обработчика

Существует несколько реализаций реактора, использующих различные механизмы демультиплексирования, предоставляемые операционной системой. ACE_Select_Reactor, как видно из названия, использует метод библиотеки сокетов select(). ACE_TP_Reactor также основывается на вызове select(), но позволяет создавать многопоточные схемы обработки событий, связанных с сокетом. ACE_WFMO_Reactor использует функцию WaitForMultipleObjects() Windows API для демультиплексирования событий. Класс ACE_Dev_Poll_Reactor использует в качестве демультиплексора /dev/poll или /dev/epoll. Класс ACE_Priority_Reactor осуществляет диспетчеризацию с использованием приоритетов. Класс ACE_Msg_WFMO_Reactor добавляет к функциональности класса ACE_WFMO_Reactor обработку сообщений Windows API. Классы ACE_XtReactor, ACE_FlReactor, ACE_QtReactor и ACE_TkReactor обеспечивают диспетчеризацию с использованием библиотек X11, Fast Light, Qt и TCL/Tk соответственно.

Каркас ACE_Task

Хорошее многопоточное приложение, занимающееся обработкой поступающих запросов, четко разделяет передачу и обработку данных. Еще таким приложениям нередко требуется организовать обмен данными/сообщениями между потоками. Для реализации этих механизмов библиотека ACE предусматривает каркас ACE_Task. Этот каркас позволяет сделать код более логичным, увязывая потоки с объектами C++, которые их создают. ACE_Task агрегирует класс ACE_Thread_Manager, позволяя прикладному коду гибко управлять одиночными потоками, а также их группами. Каркас ACE_Task агрегирует очередь сообщений ACE_Message_Queue, через которую потоки-производители могут обмениваться сообщениями с потоками-потребителями данных. Если организовать наш поток, периодически выводящий на экран текущее время, в каркас Task, то получится следующий код.

#include <ace/Task.h>

//Инкапсуляция нашей задачи
class TimerTask : public ACE_Task_Base
{
public:
int svc()
{
//Точка входа в поток
//Здесь уже можно создавать реактор
}
}

//Фрагмент кода основного потока main()
TimerTask * timer = new TimerTask;
timer->activate();
//Дожидаемся завершения задачи
timer->wait();
delete timer;

Каркас Acceptor-Connector

В предыдущем (апрельском) номере журнала мы рассматривали фасады ACE_SOCK_Acceptor и ACE_SOCK_Connector, используемые для создания клиент-серверных приложений, ориентированных на соединение. Каркас Acceptor-Connector решает те же задачи, но с точки зрения каркасного подхода. Класс ACE_Svc_Handler предоставляет точку доступа для обмена данными между сервером и клиентом. Поскольку этот класс наследуется от класса ACE_Task, который, в свою очередь, наследуется от ACE_Event_Handler, пользователю доступны все виртуальные методы (хуки) базовых классов - svc(), handle_input() и т.д. Классы ACE_Acceptor и ACE_Connector реализуют идеологию пассивного ожидания соединений и активного установления соединений со стороны сервера и клиента соответственно. Оба этих класса являются фабриками конечных точек соединения ACE_Svc_Handler, при использовании которых клиент и сервер после установки соединения могут обмениваться данными. Для получения событий каркас Acceptor-Connector использует каркас-реактор.

Каркас Proactor

Рассмотренный ранее каркас-реактор обычно используется при разработке сетевых приложений, действующих по взаимно-согласованной модели ввода/вывода. Однако когда стоит задача параллельного выполнения множества запросов с подключением нескольких процессоров и сетевых интерфейсов, использование такой модели обмена информацией чревато серьезными ошибками, связанными с синхронизацией данных. Именно поэтому для решения такого класса задач используется активно-превентивная (или асинхронная) модель обмена данными. Эта модель подразумевает разбиение транзакции передачи данных на этап инициирования транзакции и этап получения уведомления о завершении транзакции с помощью обработчика события-завершения. Каркас Proactor обеспечивает следующие преимущества по сравнению с использованием штатных средств API операционной системы. Во-первых, это переносимость кода, поскольку именно асинхронная часть библиотеки сокетов больше всего варьируется от платформы к платформе. Во-вторых, это автоматизация диспетчеризации и демультиплексирования событий завершения транзакций. В-третьих, это гибкая масштабируемость решений на основе каркаса Proactor. В-четвертых, это минимизация случайной сложности кода и максимизация повторной используемости кода. И, наконец, в-пятых, это потокобезопасность, предусмотренная в классах каркаса. Класс ACE_Proactor играет роль реактора в каркасе Acceptor-Connector. Класс ACE_Service_Handler предоставляет точку доступа к соединению. Классы ACE_Asynch_Acceptor и ACE_Asynch_Connector являются асинхронными реализациями аналогичных классов из паттерна Acceptor-Connector. Класс ACE_Handler определяет интерфейс для получения событий завершения транзакций. И, наконец, классы ACE_Asynch_Read_Stream и ACE_Asynch_Write_Stream инициируют транзакции и связывают их с объектом ACE_Handler, который принимает результат выполнения транзакции ACE_Asynch_Result.

В заключение

Остается добавить, что мы совершили экскурсию в очень мощную библиотеку промежуточного уровня, отвечающую на множество вопросов разработчиков современных кросс-платформенных распределенных систем. За бортом осталось очень много информации, которую заинтересованный читатель может найти в специальной литературе, документации по ACE и статьях Дугласа Шмидта.

WWW

http://www.cs.wustl.edu/~schmidt/ACE.html - Официальный сайт библиотеки ACE
http://www.dre.vanderbilt.edu/Doxygen - Онлайн документация по технологиям DOC
http://www.cs.wustl.edu/~schmidt/ACE-papers.html - Дополнительные статьи по ACE и смежным темам

Литература

  1. Программирование сетевых приложений на С++. т.1. Дуглас Шмидт. Стивен Хьюстон. М.: Бином. 2003 г. ISBN 5-9518-0024-2
  2. Программирование сетевых приложений на С++. т.2. Дуглас Шмидт. Стивен Хьюстон. М.: Бином. 2003 г. ISBN 5-9518-0054-4
  3. The ACE Programmer's Guide. Stephen D. Huston, James CE Johnson, Umar Syyid. Addison Wesley, 2003. ISBN 0-201-69971-0


Обсуждение статьи
Логин:
Пароль:
Регистрации на сервере не требуется. Если у вас есть форумный логин, вы можете использовать его.
Если нету, то вы можете зарегистрироваться на forum.itspecial.ru
Обсуждение этой статьи на forum.itspecial.ru
Для отправки сообщения введите код, указанный на картинке
Заголовок
Сообщение

Guest guest@gameland.ru Отправлено: 12.05.2010 9:11:41
RE: Каркасы ACE
I like this site very much replica watches buy high quality watch replicas fake chopard watches es are not just a timer,
Guest guest@gameland.ru Отправлено: 12.05.2010 9:24:52
RE: Каркасы ACE
I like this site very much nice site! replica watches While they are completely wrong lv watches Many people considered a replica
Guest guest@gameland.ru Отправлено: 11.10.2010 4:31:27
RE: Каркасы ACE
We professional wholesale new era cap,the absolute reputation guarantee and the absolute quality assurance. Various of style. Here, I believe you can find yourself like , you can choose and buy online, we will prompt delivery once you pay.
Страницы: << 1 >>

Теги: ACE, программирование


Keywords: zPOSTz zCODEz z10059z
Для Авторов: edit Lock delete Lock

Автор: Антон Палагин
Дата: 26.01.2009 12:21:41©


Другие материалы номера
Технологии защиты сети: сегодня и завтра
Кто правит балом: лидеры рынка сетевой безопасности
Дизайн защищенной сети: внедрение систем безопасности в корпоративных сетях
Навесная или интегрированная защита: что лучше?
Контроль доступа в условиях неопределенности
Программная защита сети, аппаратная защита сети
Безопасная мобильность: 10 шагов к защищенной точке беспроводного доступа
Безопасный маршрут: 10 шагов к защищенному маршрутизатору
АнтиDoS: защита от DoS-атаки средствами маршрутизатора
Борьба с утечкой информации через USB/Ethernet-порты
Азбука IPS: самые современные технологии обнаружения и предотвращения атак
Экономика резервирования данных: дифференцированный подход к бэкапу корпоративной информации
Борьба с Ring0 троянами: оригинальный способ противодействия зловредному программному обеспечению на рабочих местах
Отлажено до автоматизма: автоматизация Windows штатными средствами
Методы удаленного управления сетью
Переносимый код как решение проблем современных ОС
Демократия или диктатура: чем чреват обязательный переход на IPv6
Интеграция в Web
Карты в руки: история пластиковых карт
Интернет-деньги: основа электронной коммерции?
Электронные деньги: принципы работы и примеры реализации
Интернет-банкинг в мире и в России: история, текущее положение дел и перспективы развития

В этом разделе
Введение в SOA. Часть 1. Проектирование информационных систем
Delphi и Oracle: разрабатываем утилиту для администрирования ORACLE
Языки, которые мы потеряли
IT-практикум: Delphi и AutoCAD. Организация связи двух популярных программных комплексов
Проблемы совместного доступа к данным в Oracle
Рубиновый кофе
Королевство Zend: Инструменты для профессионального php-разработчика
Отлажено до автоматизма: автоматизация Windows штатными средствами
Каркасы ACE
Программирование в ACE: обмен данными
Программирование в ACE: параллелизм
Разделяй и властвуй: совместная разработка кода
Быстрый и меткий: Fastreport как средство корпоративной отчетности


Хакер | GameLand | Мобильные компьютеры | Купи Камеру | Total Football | All Hockey | Onboarg Magazine | Хулиган | Sync
Total DVD | DVDxpert | Maxi Tuning | (game)land company | GamePost | Свой Бизнес


Rambler's Top100