«Ни один ремесленник, который стремится к вершинам своей профессии, не примет негодных инструментов; и ни один производитель, который ценит качество работы, не будет упрашивать ремесленника принять их»
54. Разработка и использование локального сервера
Выше был рассмотрен алгоритм реализации внутрипроцессного сервера (in-proc server), который представляет собой библиотеку DLL, загружаемую в адресное пространство клиентского приложения. В этом разделе рассматривается разработка локального сервера (local server), который реализуется как самостоятельное приложение – exe-файл. Локальный сервер может быть также реализован и как DLL-библиотека, но в этом случае для него требуется использовать в качестве "носителя" специальное приложение, называемое суррогатом (surrogate). Суррогаты обеспечиваются технологией DCOM и СОМ+.
В данном разделе будет рассмотрен способ реализации сервера в качестве "обычного" приложения, разрабатываемого с помощью Delphi.
Разработка сервера.
Этап 1. Создать типовое приложение, сохранить файл проекта под требуемым именем.
Этап 2. Добавить к проекту библиотеку типов с помощью меню File\New\ActiveX\Type Library. Библиотека типов будет автоматически включена в проект (в предложение uses файла проекта). Подключение полученного *_TLB.pas файла к другим модулям проекта надо выполнить вручную.
Этап 3. Добавить к проекту СОМ объект с помощью меню File\New\ActiveX\COM Object. Delphi создаст новый модуль-заготовку для СОМ объекта (сервера) и подключит его к проекту. Можно было бы пропустить этап 2, так как при включении в приложение нового СОМ объекта, использующего библиотеку типов, файл библиотеки (*_TLB.pas) добавляется в проект автоматически.
Этап 4. Как и для случая внутрипроцессного сервера, далее требуется добавить в СОМ объект необходимые интерфейсы и методы для них с помощью редактора библиотеки типов и добавить необходимый код в функциональные методы СОМ объекта.
Этап 5. Откомпилировать проект и запустить на выполнение. При первом же запуске сервер и библиотека будут автоматически зарегистрированы в реестре Windows.
Сервер можно также зарегистрировать, запустив его на выполнение с параметром /RegServer командной строки:
Имя_сервера /RegServer
Сервер при этом на выполнение не запускается. Разрегистрация сервера выполняется так:
Имя_сервера /UnRegServer
Разработка клиентского приложения.
Приложение-клиент строится так же, как и для случая использования внутрипроцессного сервера. При запуске клиентского приложения на выполнение и вызове метода Create сокласса автоматически загружается приложение-носитель запрашиваемого СОМ объекта и выполняются методы, запрашиваемые клиентским приложением.
Сервер будет оставаться в памяти до тех пор, пока клиентское приложение будет иметь ссылку на СОМ объект. Например, если интерфейс (в клиентском приложении) описать как глобальную переменную, то сервер будет оставаться в памяти до тех пор, пока эта переменная будет существовать, т.е. до окончания работы клиентского приложения. Если ссылка на интерфейс будет описана как локальная переменная в какой-либо подпрограмме, то сервер будет выгружен из памяти при завершении работы этой подпрограммы. При попытке закрытия приложения сервера в тот момент, когда клиентское приложение имеет ссылку на СОМ объект, будет выдано предупреждение (заголовок окна – COM Server Warning) о том, что сервер используется другим приложением.
При запуске на выполнение нескольких экземпляров клиентских приложений приложение-сервер будет запущено только в одном экземпляре, если при включении СОМ объекта в проект были оставлены значения его свойств, предлагаемые по умолчанию.
Запуск сервера сопровождается появлением главного окна приложения. Это окно можно скрыть, если, например, в обработчике события OnPaint вызвать метод Hide для того, чтобы скрыть главное окно приложения. В этом случае при запуске приложения-сервера на выполнение (обычным образом или из клиентского приложения) главное окно приложения появляться не будет. Такое решение не очень подходит, так как при автономном запуске локального сервера его главное окно должно появляться. Выход – анализ командной строки на предмет наличия ключа /Embedding или –Embedding. Например, можно добавить в приложение такой обработчик события OnPaint:
Procedure TForm1.FormPaint(Sender: TObject);
var
s : PChar;
Begin
s:=GetCommandLine();
if (Pos('/Embedding',s)<>0) or (Pos('-Embedding',s)<>0)
then Form1.Hide;
End;
По всей видимости, лучший выход – это перехват сообщения об открытии или прорисовке окна или перекрытие соответствующего метода главной формы приложения.
Client.exe на Windows 98
Client.exe на Windows NT 4.0
«53. Алгоритм взаимодействия клиент-сервер»
55. Интерфейсы