Что такое динамический обмен данными

Технология динамического обмена данными DDE

Дата добавления: 2014-10-02 ; просмотров: 7141 ; Нарушение авторских прав

Клиент DDE. В качестве приложения клиента может выступать любое приложение, позволяющее осуществлять DDE-запросы к DDE-серверу. В качестве примера приложения, обладающего возможностями DDE-клиента, можно привести электронную таблицу Microsoft Excel, позволяющую в качестве формулы в какой-либо ячейке устанавливать запрос с автообновлением данных к указываемому DDE-серверу.

Сервер DDE. Приложение, обеспечивающее возможности сервера, должно “уметь” принимать DDE сообщения и посылать данные в ответ на запросы приложений-клиентов. У одного DDE-сервера может быть один или несколько DDE-клиентов.

Сеанс DDE – активная непрерывная связь между клиентом и сервером.

Транзакция DDE – одиночный акт обмена данными в процессе сеанса.

В DDE используется трёхуровневая система адресации: service (зарегистрированный сервис, как правило, указывается приложение, предоставляющее серверные функции); topic (раздел данных, например, имя файла, или таблица базы данных); item (элемент данных, подлежащий передаче).

Если в качестве сервера DDE выступает MS Excel, эта схема выглядит следующим образом: service – «EXCEL»; topics – электронная таблица «[Книга1]Лист1»; item –ячейка «R1C2».

Поскольку Windows базируется на архитектуре, использующей сообщения, то наиболее подходящим методом для автоматической передачи данных между прикладными программами является посылка сообщений. Все транзакции выполняются с помощью передачи между программами клиентом и сервером DDE сообщений:

WM_DDE_INITIATE – инициализирует диалог между прикладными программами сервера и клиента;

WM_DDE_ACK – посылается в ответ на полученное сообщение;

WM_DDE_REQUEST – запрашивает у сервера значение элемента данных;

WM_DDE_POKE – посылает значение элемента данных серверу;

WM_DDE_ADVISE – устанавливает постоянную связь между сервером и клиентом;

WM_DDE_DATA – посылает значение элемента данных клиенту;

WM_DDE_EXECUTE – посылает строку прикладной программе-серверу, которая должна выполнить ее как последовательность команд;

WM_DDE_UNADVISE – завершает постоянную связь между сервером и клиентом;

WM_DDE_TERMINATE – завершает диалог.

Посылка сообщений – это нижний уровень обмена данными между DDE-клиентом и DDE-сервером. На верхнем уровне DDE-обмен реализован в виде функций, содержащихся в динамической библиотеке DDEML.DLL.

С целью расширения возможностей стандартного протокола DDE на локальную сеть предложен NetDDE. Он позволяет приложениям, запущенным на компьютерах, объединенных в локальную сеть, вести DDE-обмен.

Источник

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Содержание

История и архитектура

Динамический обмен данными был впервые представлен в 1987 году с выпуском Windows 2.0 как метод межпроцессного взаимодействия чтобы одна программа могла взаимодействовать с другой программой или управлять ею, что-то вроде RPC Sun (Удаленный вызов процедур). [1] В то время единственным способом связи между операционной системой и клиентскими приложениями был «Уровень обмена сообщениями Windows». DDE расширил этот протокол, чтобы разрешить одноранговую связь между клиентскими приложениями посредством широковещательной рассылки сообщений.

Поскольку DDE работает через широковещательные сообщения, он уязвим для любого кода управления окнами, который не сообщения насоса. Эта проблема не рассматривалась при разработке DDE, потому что DDE предшествует упреждающая многозадачность. [2]

Более того, любой код, управляющий дескриптором окна, может отвечать на широковещательную рассылку DDE; инициатор DDE должен различать ожидаемые и неожиданные ответы. Собеседники DDE обычно выражают, какую информацию они ищут, в терминах иерархической нить ключи. Например, клетка в Майкрософт Эксель был известен DDE под своим «прикладным» именем. Каждое приложение может дополнительно систематизировать информацию по группам, известным как «темы», и каждая тема может обслуживать отдельные фрагменты данных как «элемент». Например, если пользователь хочет получить значение из Microsoft Excel, которое содержится в электронной таблице с именем «Book1.xls» в ячейке в первой строке и первом столбце, приложение будет «Excel», тема «Book1». xls »и элемент« r1c1 ». Затем внутренние изменения в ячейке из-за действий Excel будут передаваться (в обратном порядке) вызывающему приложению посредством дополнительных широковещательных сообщений.

Отношение к современным технологиям автоматизации

Обычно DDE используется в специально разработанных приложениях для управления стандартным программным обеспечением. Например, собственное пользовательское приложение может использовать DDE для открытия Майкрософт Эксель электронную таблицу и заполните ее данными, открыв диалог DDE с Excel и отправив ему команды DDE. Эта функция была в основном заменена Компонентная объектная модель набор технологий. Microsoft не использовала DDE для внутренних целей с момента выпуска Windows 95. [3] Например, Excel теперь предоставляет обширную OLE автоматизация объектная модель, которая является рекомендуемым методом для связи с Excel. Однако этот метод все еще используется, особенно для распространения финансовых данных. [4] Поскольку DDE не требует большего количества компонентов операционной системы, чем обычная Windows GUI программа, это также [малоиспользуемая] альтернатива для программ, стремящихся минимизировать свои зависимости.

NetDDE

Microsoft лицензировала базовую (Кадры NetBIOS только) версия продукта для включения в различные версии Windows из Windows для рабочих групп к Windows XP. Кроме того, Wonderware также продала своим клиентам улучшенную версию NetDDE, которая включала поддержку TCP / IP. Технология широко используется в SCADA поле. Основные приложения Windows, использующие NetDDE: Просмотрщик буфера, WinChat и Microsoft Hearts.

NetDDE все еще был включен в Windows Server 2003 и Windows XP Service Pack 2, хотя по умолчанию он был отключен. Он был полностью удален в Виндоус виста. [5] Однако это не помешает установке и работе существующих версий NetDDE в более поздних версиях Windows.

Источник

Динамический обмен данными

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

В списке изучаемых в данной главе способов межпрограммного взаимодействия технология DDE (Dynamic Data Exchange – динамический обмен данными) является весьма старой; по древности ее опережает лишь буфер обмена.

Технология DDE была разработана в недрах Microsoft еще для первых версий Windows и с тех времен не претерпела серьезных изменений. Однако пожилой возраст технологии нельзя считать серьезным поводом для досрочного списания DDE со счетов. Одно из ключевых преимуществ DDE над современными методами совместной работы приложений заключается в малой требовательности к ресурсам компьютера (разве можно сравнить вычислительные возможности современного Pentium IV с компьютером на базе 286 микропроцессора, для которого создавалась DDE). К списку достоинств DDE стоит отнести и относительную простоту программной реализации этого процесса.

Основная задача DDE – обеспечить обмен данными между двумя приложениями: клиентом и сервером. В простейшем случае процесс передачи односторонний – клиент DDEинициирует процесс, запрашивая необходимые ему данные. Если сервер DDEв состоянии ответить на запрос, он отправляет требуемые данные клиенту DDE. Процесс передачи данных называют сеансом обмена DDE.

В обязанности клиента входит лишь правильная организация запроса. На стороне сервера DDE реализуется алгоритм ответа на запросы клиента, поэтому с точки зрения программирования задача создания сервера несколько сложнее, чем задача написания клиента. В свою очередь клиент также способен отправить команду серверу, однако сервер по праву старшинства может отказаться от ее выполнения. Одно и то же приложение может одновременно выступать и в роли сервера, и в роли клиента DDE, но в таком случае требуется сформировать два различных диалога динамического обмена.

Открытие сеанса DDE инициируется на клиентской стороне. Эту операцию с некоторой степенью приближения можно сравнить с процессом заказа авиабилета по телефону. Вы набираете телефонный номер службы заказов, вступаете в разговор с оператором на тему «что летит в Магадан» и заказываете билет на устраивающий вас рейс. Если вы попытаетесь общаться с сервером на незнакомую ему тему или инициируете сеанс с искаженным именем сервиса, то, увы, сеанс DDE не состоится.

Для обмена данными протокол DDE предполагает отправку клиентским приложением запроса, включающего три элемента:

1. Определение имени сервиса (Service Name) обеспечит доступ к интересующему нас приложению-серверу DDE (аналог – набор телефонного номера службы заказа).

2. Указание, на какую тему (topic) вы хотите поговорить с сервером («что летит в Магадан»).

3. Выбор в теме соответствующего предмета обсуждения (item) – заказ билета.

Для разработки приложений, способных поддерживать сеанс DDE, в Delphi созданы четыре специальных класса: TDDEClientConv, TDDEClientItem, TDDEServerConv и TDDEServerItem. По их названиям можно догадаться, что два первых элемента управления специализируются на создании клиентских приложений, а два последних нацелены на реализацию приложения-сервера DDE.

Непосредственно за организацию контакта отвечают классы TDDEClientConv и TDDEServerConv.

На основе перечисленных классов реализованы невизуальные компоненты; они размещены на странице System палитры компонентов Delphi.

Источник

Сведения о платформа динамических данных Exchange

Windows предоставляет несколько методов передачи данных между приложениями. одним из способов является использование протокола платформа динамических данных Exchange (DDE). Протокол DDE — это набор сообщений и руководств. Он отправляет сообщения между приложениями, которые совместно используют данные, и использует общую память для обмена данными между приложениями. Приложения могут использовать протокол DDE для одноразовой передачи данных и для непрерывного обмена, при котором приложения отправляют обновления друг другу по мере того, как новые данные становятся доступными.

Windows также поддерживает библиотеку управления платформа динамических данных Exchange (ддемл). ДДЕМЛ — это библиотека динамической компоновки (DLL), которую приложения могут использовать для совместного использования данных. ДДЕМЛ предоставляет функции и сообщения, упрощающие задачу добавления возможностей DDE в приложение. Вместо отправки, публикации и обработки сообщений DDE напрямую приложение использует функции ДДЕМЛ для управления сеансами DDE. (Сеанс DDE — это взаимодействие между клиентскими и серверными приложениями.)

ДДЕМЛ также предоставляет средство для управления строками и данными, которые совместно используют приложения DDE. Вместо использования атомов и указателей на объекты общей памяти приложения DDE создают и обмениваются дескрипторами строк, которые обозначают строки и дескрипторы данных, определяющие объекты памяти. ДДЕМЛ также позволяет серверному приложению регистрировать имена служб, которые она поддерживает. Имена передаются в другие приложения в системе, которые могут использовать имена для подключения к серверу. Более того, ДДЕМЛ обеспечивает совместимость приложений DDE, представляя их единообразно реализовать протокол DDE.

Существующие приложения, использующие протокол DDE на основе сообщений, полностью совместимы с теми, которые используют ДДЕМЛ. Это значит, что приложение, использующее DDE на основе сообщений, может устанавливать диалоги и выполнять транзакции с приложениями, использующими ДДЕМЛ. Из-за множества преимуществ ДДЕМЛ новые приложения должны использовать его, а не сообщения DDE. Чтобы использовать элементы API ДДЕМЛ, необходимо включить в исходные файлы файл заголовка ДДЕМЛ, связать с библиотекой ДДЕМЛ и убедиться, что библиотека динамической компоновки ДДЕМЛ находится в системном пути поиска.

В этом разделе рассматриваются следующие темы.

протокол Exchange платформа динамических данных

так как Windows имеет архитектуру на основе сообщений, передача сообщений является наиболее подходящим методом для автоматической передачи информации между приложениями. Однако сообщения содержат только два параметра (wParam и lParam) для передачи данных. В результате эти параметры должны ссылаться косвенно на другие фрагменты данных, когда между приложениями передаются несколько слов данных. Протокол DDE точно определяет, как приложения должны использовать параметры wParam и lParam для передачи больших фрагментов данных с помощью глобальных атомов и дескрипторов общей памяти. Протокол DDE имеет определенные правила для выделения и удаления глобальных атомов и объектов общей памяти.

Глобальный Atom — это ссылка на символьную строку. В протоколе DDE атомы идентифицируют приложения, которые обмениваются данными, характер обмена данными и сами элементы данных. Дополнительные сведения о атомах см. в разделе о атомах.

использование для Windows платформа динамических данных Exchange

Протокол DDE наиболее подходит для обмена данными, который не требует текущего взаимодействия с пользователем. Как правило, приложение предоставляет пользователю способ установить связь между приложениями, которые обмениваются данными. Однако после того, как связь установлена, приложения обмениваются данными без участия пользователя.

DDE можно использовать для реализации широкого спектра функций приложений, например:

платформа динамических данных Exchange с точки зрения пользователя

В следующем примере показано, как могут взаимодействовать два приложения DDE, как видно из точки зрения пользователя.

пользователь электронной таблицы хочет использовать Microsoft Excel для контроля цены на конкретный запас на бирже в нью-йорке Exchange. У пользователя есть приложение с именем quote, которое, в свою очередь, имеет доступ к данным Нисе. сеанс DDE между Excel и квотой происходит следующим образом:

основные понятия Exchange платформа динамических данных

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

Клиент, сервер и беседа

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

Сеанс DDE происходит между двумя окнами, по одному для каждого из участвующих в приложении приложений. Окно может быть основным окном приложения; окно, связанное с конкретным документом, как в приложении с многодокументным интерфейсом (MDI); или скрытое (невидимое) окно, предназначенное только для обработки сообщений DDE.

Так как сеанс DDE определяется парой дескрипторов для окон диалога, ни одно окно не должно быть вовлечено в несколько диалогов с другим окном. Клиентское приложение или серверное приложение должно предоставлять другое окно для каждого диалога с конкретным сервером или клиентским приложением.

Приложение может обеспечить, чтобы пара клиентских и серверных окон никогда не участвовала в нескольких диалогах, создавая скрытое окно для каждого диалога. Единственное назначение этого окна — Обработка сообщений DDE.

Имена приложений, разделов и элементов

Протокол DDE определяет единицы данных, передаваемых между клиентом и сервером с трехуровневой иерархией имен приложений, разделов и элементов.

Каждый сеанс DDE однозначно определяется именем приложения и темой. В начале сеанса DDE клиент и сервер определяют имя приложения и раздел. Имя приложения обычно является именем серверного приложения. например, если Excel выступает в качестве сервера в диалоге, имя приложения будет Excel.

Раздел DDE представляет собой общую классификацию данных, в которой во время диалога несколько элементов данных могут быть «обсуждаемыми» (в Exchange). Для приложений, работающих с документами на основе файлов, раздел обычно представляет собой имя файла. Для других приложений раздел является именем, зависящим от приложения.

Так как окно клиента и сервера обрабатываются совместно, определите сеанс DDE, имя приложения и раздел, описывающие диалог, не могут быть изменены во время диалога.

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

Раздел System

Приложения должны поддерживать системный раздел все время. В этом разделе представлен контекст для информации, которая может представлять собой общий интерес для другого приложения.

Значения элементов данных должны подготавливаться к просмотру в формате _ текстовых буферов CF. Отдельные элементы значений элементов для системного раздела должны быть разделены символами табуляции. В следующей таблице представлены некоторые элементы для системного раздела.

Постоянные ссылки на данные

После начала сеанса DDE клиент может установить одну или несколько постоянных ссылок на данные с сервера. Канал передачи данных — это механизм связи, с помощью которого сервер уведомляет клиента при каждом изменении значения указанного элемента данных. Канал данных является постоянным в том смысле, что этот процесс уведомления будет продолжаться до тех пор, пока не завершится связь с данными или сеанс DDE.

Существует два вида постоянных ссылок на данные DDE: горячий и горячий. В канале горячий передачи данных сервер уведомляет клиента о том, что значение элемента данных изменилось, но сервер не отправляет клиенту значение данных, пока клиент не запросит его. В канале горячего передачи данных сервер немедленно отправляет клиенту измененное значение данных.

Приложения, поддерживающие горячую или горячую связь, обычно предоставляют команду Копировать или Вставить ссылку в своем меню » Правка «, чтобы позволить пользователю устанавливать ссылки между приложениями.

Атомы и объекты общей памяти

DDE использует объекты общей памяти для трех целей:

Приложение, получающее объект общей памяти DDE, должно обрабатывать его как доступное только для чтения. Приложение не должно использовать объект в качестве обоюдной области для чтения и записи для бесплатного обмена данными.

Как и в случае с Atom DDE, приложение должно освободить объект общей памяти для эффективного управления памятью. Приложение также должно блокировать и разблокировать объекты памяти.

общие сведения о сообщениях Exchange платформа динамических данных

Так как DDE является протоколом на основе сообщений, он не использует никаких функций или библиотек. Все транзакции DDE проходят через передачу определенных сообщений DDE между клиентскими и серверными окнами.

Имеется девять сообщений DDE; Символьные константы для этих сообщений определяются в файле заголовка DDE. Некоторые структуры для различных сообщений DDE также определяются в этом файле заголовка.

В следующей таблице перечислены сообщения DDE.

СообщениеОписание
WM _ DDE _ ACKПодтверждает получение или отсутствие получения сообщения.
Протокол WM _ DDE _ adviseЗапрашивает серверное приложение на предоставление обновления или уведомления для элемента данных при каждом изменении. Это устанавливает постоянный канал данных.
_данные DDE _ WMОтправляет в клиентское приложение значение элемента данных.
_выполнение WM DDE _Отправляет строку в серверное приложение, которое предполагает обработку строки в виде последовательности команд.
_Запуск WM DDE _Инициирует диалог между клиентскими и серверными приложениями.
_Вставка DDE _ WMОтправляет значение элемента данных в серверное приложение.
_запрос DDE _ WMЗапрашивает серверное приложение для предоставления значения элемента данных.
_прерывание работы WM DDE _Завершает диалог.
WM _ DDE _ unadviseЗавершает связь с постоянными данными.

платформа динамических данных сообщение Exchange Flow

Типичный сеанс DDE состоит из следующих событий.

Клиентское приложение инициирует диалог, и серверное приложение отвечает.

Приложения обмениваются данными с помощью любого или всех следующих методов:

Клиент или серверное приложение завершает диалог.

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

Клиент может устанавливать диалоги с несколькими серверами. сервер может иметь диалоги с несколькими клиентами. При обработке сообщений из более чем одного источника клиент или сервер должен синхронно обрабатывать сообщения диалога, но не должны обрабатывать все сообщения синхронно. Иными словами, он может переходить от одного диалога к другому при необходимости.

Приложение должно быть способно обработать сбой клиента или сервера для реагирования на сообщение в течение определенного времени. Так как интервал времени ожидания может различаться в зависимости от характера приложения и конфигурации системы пользователя (включая подключение к сети), приложение должно предоставить пользователю способ указания интервала в.

Функции упаковки параметров

платформа динамических данных Exchange и олицетворение

Источник

Операционная система Microsoft Windows 3.1 для программиста. Дополнительные главы

3. Обмен данными через DDE

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

В предыдущей главе мы рассмотрели возможность передачи данных из одного приложения в другое через универсальный буфер обмена Clipboard. При этом обмен данными носит эпизодический характер и находится под контролем пользователя. Пользователь выделяет фрагмент документа, копирует его в Clipboard и затем вставляет в другой или тот же самый документ.

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

Предметом нашего изучения в этой главе будет механизм динамического обмена данными DDE (Dynamic Data Exchange), позволяющий создать постоянно действующие каналы между несколькими одновременно работающими приложениями Windows. Эти каналы могут создаваться автоматически при запуске приложения или при необходимости, а также по явному запросу пользователя. После того как каналы созданы, они будут работать без вмешательства пользователя.

В операционной системе Windows версии 3.0 механизм DDE был реализован через передачу сообщений с помощью хорошо известной вам функции SendMessage с использованием глобальных блоков памяти, доступных всем приложениям. Фактически при создании DDE-приложений программист был вынужден вникать во все детали процесса создания канала связи, придерживаясь определенного в SDK протокола. Поэтому использованию динамического обмена данных DDE сопутствовали многочисленные затруднения.

Библиотека DDEML хороша сама по себе, так как она упрощает DDE-приложения и избавляет программиста от учета утомительных деталей протокола обмена сообщениями. Однако есть еще две причины, по которой следует пользоваться этой библиотекой.

Во-первых, в новых версиях Windows, а также в операционной системе Windows NT динамический обмен данных организуется исключительно с помощью библиотеки DDEML. Поэтому если в будущем вы собираетесь переносить свое приложение в среду Windows NT или Windows-95, имеет смысл сразу ориентироваться на работу с DDEML.

Во-вторых, вспомним о существовании такой операционной системы, как Windows for Workgroups. Сетевые возможности Windows for Workgroups базируются на сетевом динамическом обмене данными Network DDE (операционная система Windows NT также поддерживает Network DDE).

Механизм Network DDE позволяет организовать каналы обмена данными между приложениями, которые запущены на разных рабочих станциях сети. Поэтому освоение «обычной» библиотеки DDEML можно считать первым шагом на пути к изучению сетевых возможностей различных версий Windows.

Исходя из сказанного выше, мы считаем нецелесообразным изучение устаревшего протокола обмена сообщениями DDE. Вместо этого мы сразу займемся библиотекой DDEML, ставшей стандартным средством организации динамического обмена данными в операционной системе Windows.

3.1. Архитектура «клиент-сервер»

Прежде всего, определимся с терминологией.

Клиентом и сервером мы будем называть процессы (программы или приложения), работающие одновременно на одном или разных компьютерах (объединенных в сеть), и взаимодействующих между собой определенным образом.

Клиент посылает серверу запрос на получение данных или выполнение какой-либо работы (рис. 3.1). Это может быть запрос к серверу базы данных, задание серверу резервного копирования дисков или что-то аналогичное.

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Рис. 3.1. Взаимодействие между клиентом и сервером

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

Процесс передачи запроса серверу мы будем называть транзакцией.

Транзакция называется завершенной, если выполнены все три действия. Если же на одном из трех этапов произошел сбой, транзакция останется незавершенной. После восстановления незавершенная транзакция откатывается, что необходимо в ряде случаев для сохранения целостности данных (разумеется, за правильное выполнение отката транзакции отвечает сервер).

Например, если сервер базы данных получил от клиента запрос на обновление записей в нескольких файлах и перед аварийным отключением электропитания успел выполнить только часть работы, после восстановления ему необходимо восстановить состояние базы данных на момент начала незавершенной транзакции.

Топология системы, имеющей архитектуру «клиент-сервер», может быть различной. На рис. 3.1 показана система, состоящая из одного клиента и одного сервера. Однако в системе может быть несколько клиентов, работающих с одним сервером (рис. 3.2), или несколько клиентов, работающих одновременно с несколькими серверами (рис. 3.3).

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Рис. 3.2. Система с одним сервером и несколькими клиентами

Обратите внимание на пунктирную линию, соединяющую серверы на рис. 3.3. Между серверами тоже может идти обмен транзакциями. Таким образом, любой процесс может выступать одновременно и клиентом, и сервером.

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Рис. 3.3. Система с двумя серверами и несколькими клиентами

Очень хорошо, скажете вы, но причем тут DDE?

Библиотека DDEML позволяет создавать системы, имеющие различные топологии. В среде Windows версии 3.1 в качестве клиентов и серверов могут выступать приложения, работающие на одном компьютере. В локальной сети, созданной на базе операционных систем Windows for Workgroups и Windows NT, клиентами и серверами могут быть приложения, работающие на разных компьютерах.

3.2. Инициализация и создание канала связи

В процессе инициализации сервер должен выполнить такие действия:

зарегистрировать себя в библиотеке DDEML;

зарегистрировать предоставляемый сервис, которым сможет воспользоваться приложение-клиент

Клиент должен сделать следующее:

зарегистрировать себя в библиотеке DDEML;

создать канал связи с сервером, указав необходимый сервис

Рассмотрим эти действия подробнее.

Регистрация в библиотеке DDEML

Библиотека DDEML используется одновременно многими приложениями, однако, подобно всем DLL-библиотекам, находится в оперативной памяти в единственном экземпляре. Функция LibMain, выполняющая инициализацию DLL-библиотеки, вызывается только один раз при первой загрузке библиотеки в память (для Windows версии 3.1), поэтому LibMain не может использоваться для регистрации приложений.

Если приложение собирается использовать DDEML, оно должно зарегистрировать себя в библиотеке DDEML, вызвав специально предназначенную для этого функцию с именем DdeInitialize.

Прототип функции DdeInitialize определен в файле ddeml.h (который должен быть включен в исходный текст DDEML-приложения наряду с файлом windows.h):

UINT WINAPI DdeInitialize(

DWORD FAR* pidInst, // адрес идентификатора приложения

PFNCALLBACK pfnCallback, // адрес функции обратного вызова

Функция DdeInitialize используется в процессе инициализации и серверов, и клиентов DDEML. Сама по себе она не создает никаких каналов передачи данных между приложениями, однако процедура регистрации приложения, выполняемая этой функцией, должна быть проведена до вызова любых других функций, имеющих отношение к DDEML.

Займемся параметрами функции DdeInitialize.

Параметр pidInst представляет собой указатель на двойное слово, в которое после регистрации будет записан идентификатор, присвоенный копии приложения библиотекой DDEML (одновременно могут работать несколько копий одного и того же DDEML-приложения). Иными словами, в процессе регистрации библиотека DDEML присваивает копии приложения некоторый идентификатор, под которым она его «знает». Вы должны указывать полученный от функции идентификатор при вызове всех остальных функций библиотеки DDEML.

Перед вызовом функции DdeInitialize ваше приложение должно записать в двойное слово, адрес которого передается через первый параметр, нулевое значение.

Параметр pfnCallback представляет собой указатель на функцию обратного вызова, определенную приложением для обработки транзакций. Как сервер, так и клиент должны определить такую функцию. Функция обратного вызова вызывается системой DDEML и содержит в себе всю логику обработки транзакций, определенную вами при разработке приложения.

Если приложение вызывает функцию DdeInitialize несколько раз для многократной регистрации, каждый раз следует указывать отдельную функцию обратного вызова. Многократная регистрация вполне допустима, так как каждый раз библиотека DDEML будет создавать для себя новый идентификатор приложения. Такая методика используется при создании DLL-библиотек, работающих с DDEML. Обычным приложениям достаточно зарегистрировать себя один раз и, соответственно, определить одну функцию обратного вызова.

Через параметр afCmd передается двойное слово, каждый бит которого является флагом, определяющим режимы работы канала связи, а также влияющие на действия, выполняемые функцией DdeInitialize.

Последний параметр с именем ulRes зарезервирован и должен иметь нулевое значение.

Приведем фрагмент кода, выполняющего регистрацию сервера в библиотеке DDEML:

В этом фрагменте вначале создается переходник для функции обратного вызова, затем адрес этого переходника указывается во втором параметре функции DdeInitialize.

В случае успеха функция DdeInitialize возвращает нулевое значение. Для проверки можно также использовать константу DMLERR_NO_ERROR, определенную в файле ddeml.h. Если произошла ошибка, возвращается ненулевой код ошибки. Соответствующие константы определены в файле ddeml.h и имеют префикс имени DMLERR.

Немного о флагах, передаваемых через параметр afCmd.

Символические константы с префиксом имени APPCLASS позволяют задать класс приложения с точки зрения использования DDEML.

Класс APPCLASS_STANDARD предназначен для регистрации стандартного DDEML-приложения. Этот класс использован в приведенном выше фрагменте кода и в приложении DDEMLSR, исходные тексты которого вы увидите позже.

Класс APPCLASS_MONITOR предназначен для отладчиков и других приложений, управляющих работой системы DDEML. В качестве примера можно привести приложение DDESpy. Это приложение поставляется в составе Microsoft SDK for Windows 3.1 и предназначено для отладки DDE-приложений (и, разумеется, DDEML-приложений). В конце данной главы мы научим вас использовать приложение DDESpy для отладки созданных вами DDE-приложений.

Символические константы с префиксом имени APPCMD позволяют конкретизировать функции, выполняемые приложением, и экономить системные ресурсы. Если DDEML-приложение выполняет только функции клиента, следует указать флаг APPCMD_CLIENTONLY:

В простейших случаях можно ограничиться использованием класса APPCLASS_STANDARD при создании сервера DDEML и флага APPCMD_CLIENTONLY при создании клиента DDEML. Мы так и поступили в наших приложениях DDEMLSR и DDEMLCL, выполняющих, соответственно, функции сервера и клиента DDEML. Остальные флаги влияют на то, когда и зачем будет вызываться функция обратного вызова.

Если приложение больше не собирается работать с библиотекой DDEML, оно должно вызвать функцию DdeUninitialize, передав ей в качестве единственного параметра идентификатор копии приложения, полученный от функции DdeInitialize:

Регистрация сервиса

Следующий этап в инициализации сервера DDEML заключается в регистрации предоставляемого им сервиса.

Сервер DDEML может предоставлять сервис одного или нескольких видов. Как правило, один сервер предоставляет только один сервис, причем текстовая строка, идентифицирующая сервис, часто совпадает с именем приложения. Но можно выбрать любую другую строку. Например, наше приложение DDEMLSR предоставляет сервис «BMPService». Как можно догадаться из названия, этот сервис связан с bmp-файлами (в действительности мы привели сильно упрощенную версию сервера bmp-файлов, в которой для сокращения объема листингов изъяты функции обслуживания bmp-файлов).

Канал DDEML служит для передачи блоков данных. В рамках одного раздела сервер может обмениваться с клиентом разными блоками данных, каждый из которых идентифицируется при передаче именем элемента данных. В процессе создания канала связи не требуется указывать элементы данных.

Для иллюстрации сказанного выше предположим, что мы создаем сервер BMPSERV.EXE, предназначенный для отображения битовых изображений DIB, причем путь к соответствующему bmp-файлу и управляющая информация должны передаваться серверу через канал связи DDE.

При регистрации сервер BMPSERV.EXE регистрирует один сервис «BMPServer» и два раздела: «BMPFile» и «Control» (рис. 3.4).

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Рис. 3.4. Сервис, разделы и элементы данных для сервера BMPSERV

В разделе «BMPFile» определены элементы данных «Filename» (имя отображаемого bmp-файла) и «Title» (заголовок изображения или подпись под изображением). В разделе «Control» определен один элемент данных «Mode», определяющий режим отображения (размеры и расположение окна, органы управления для работы с изображением и т. п.).

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

Регистрация сервиса выполняется сервером DDEML обычно сразу после вызова функции DdeInitialize и выполняется в два этапа.

На первом этапе текстовая строка имени сервиса сохраняется в специальной системной таблице (таблице атомов), для чего вызывается функция DdeCreateStringHandle:

Через параметр idInst приложение должно передать идентификатор, полученный на этапе регистрации приложения в библиотеке DDEML функцией DdeInitialize.

Параметр psz представляет собой указатель на текстовую строку, закрытую двоичным нулем. Размер этой строки не должен превышать 255 байт.

В качестве значения для параметра iCodePage можно указать CP_WINANSI (эта константа равна нулю). Можно также использовать значение, полученное от функции GetKBCodePage. Функция GetKBCodePage не имеет параметров и возвращает номер текущей кодовой страницы.

Идентификатор текстовой строки, возвращенный функцией DdeCreateStringHandle и соответствующий регистрируемому сервису, следует передать функции DdeNameService:

Через параметр idInst приложение должно передать идентификатор, полученный на этапе регистрации приложения в библиотеке DDEML функцией DdeInitialize.

Параметр hsz1 предназначен для передачи имени сервиса через идентификатор текстовой строки, возвращенной функцией DdeCreateStringHandle.

Параметр hsz2 зарезервирован, для него следует использовать нулевое значение.

При регистрации сервиса через параметр afCmd следует передать значение DNS_REGISTER (регистрация сервиса). Сервер DDEML в процессе своей работы может динамически регистрировать и отменять виды предоставляемого сервиса. Для отмены сервиса через параметр afCmd передается значение DNS_UNREGISTER.

Перед завершением работы сервер DDEML должен отменить весь зарегистрированный им ранее сервис, вызвав функцию DdeInitialize с параметром afCmd, имеющим значение DNS_UNREGISTER.

Приведем фрагмент кода, выполняющего регистрацию сервиса «BMPServer»:

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

Отметим, что регистрацию сервиса выполняет только сервер DDEML. Что же касается создания идентификаторов текстовых строк функцией DdeCreateStringHandle, то эта операция выполняется как сервером, так и клиентом. Полученные идентификаторы используются при создании канала и в процессе передачи данных.

Зная идентификатор строки, приложение может получить строку, вызвав функцию DdeQueryString:

Назначение параметров понятно из комментариев в прототипе функции.

Если идентификатор созданной текстовой строки используется в функции обратного вызова (которую мы рассмотрим чуть позже), за освобождение ресурсов, связанных с текстовой строкой, отвечает система DDEML. В противном случае приложение должно самостоятельно уничтожать созданные им идентификаторы, вызывая функцию DdeFreeStringHandle:

Функция обратного вызова DDEML

Когда сервер или клиент регистрирует себя в библиотеке DDEML при помощи функции DdeInitialize, он указывает адрес переходника, созданного для функции обратного вызова. Функция обратного вызова предназначена для обработки всех событий, возникающих в процессе создания каналов связи и передачи данных.

В простейшем случае функция обратного вызова сервера DDEML может выглядеть следующим образом:

Функция обратного вызова должна быть определена как экспортируемая, поэтому мы указали ключевое слово _export.

Через первый параметр wType передается код транзакции. Подобно функции окна, которая обрабатывает сообщения, функция обратного вызова DDEML выполняет обработку транзакций. В зависимости от кода транзакции и результата обработки функция обратного вызова DDEML возвращает то или иное значение.

Второй параметр задает код формата передаваемых данных. Для кодов формата используются те же значения, что и для форматов Clipboard, например, CF_TEXT.

Через параметр hConv передается идентификатор канала передачи данных (который мы еще не научились создавать).

Назначение остальных параметров функции обратного вызова зависит от кода транзакции. В приведенном выше фрагменте кода используются символические имена кодов транзакций, определенные в файле ddeml.h, и имеющие префикс имени XTYP. В дальнейшем мы подробно расскажем о некоторых транзакциях, использованных в наших приложениях.

Функция обратного вызова для клиента DDEML выглядит точно также, отличаясь лишь составом обрабатываемых транзакций. Приведем для примера исходный текст такой функции из нашего приложения DDEMLCL:

При регистрации приложения в библиотеке DDEML функцией DdeInitialize можно указать флаги, запрещающие или разрешающие поступление транзакций некоторых типов в функцию обратного вызова. Запретив вызов функции обратного вызова для необрабатываемых транзакций, можно ускорить работу приложения.

Создание и уничтожение канала

Кто является инициатором создания канала?

Канал связи между клиентом и сервером создается всегда по инициативе клиента. После регистрации в библиотеке DDEML клиент вызывает функцию DdeConnect, создающую канал связи:

Через параметр idInst приложение должно передать идентификатор, полученный на этапе регистрации приложения в библиотеки DDEML функцией DdeInitialize.

Параметры hszService и hszTopic предназначены для передачи идентификаторов строк, содержащих, соответственно, имена сервиса и раздела. Эти идентификаторы были получены нами ранее при помощи функции DdeCreateStringHandle.

В нашем приложении DDEMLCL для создания канала с сервером используется следующий фрагмент кода:

Идентификатор канала, полученный от функции DdeConnect, следует сохранить для обеспечения возможности получения данных от сервера.

Что же происходит, когда клиент создает канал, вызывая функцию DdeConnect?

Прежде всего, библиотека DDEML посылает транзакцию с кодом XTYP_CONNECT всем активным серверам, которые зарегистрировали сервис, указанный во втором параметре функции DdeConnect.

Для транзакции XTYP_CONNECT параметры функции обратного вызова принимают следующие значения:

ПараметрЗначение
hsz1Идентификатор строки, содержащей имя раздела
hsz2Идентификатор строки, содержащей имя сервиса
dwData1Адрес структуры CONVCONTEXT
dwData2Если значение равно TRUE, данная копия приложения является одновременно и клиентом, и сервером. Если же значение равно FALSE, клиент и сервер являются разными приложениями или разными копиями приложения

Обработчик транзакции XTYP_CONNECT, расположенный в функции обратного вызова сервера, должен проверить сервис и раздел, идентификаторы которых переданы через параметры функции. Если сервер поддерживает этот сервис и раздел, можно создавать канал. В таком случае функция обратного вызова должна вернуть значение TRUE. Иначе следует вернуть FALSE.

Приведенный ниже фрагмент кода, взятый из нашего приложения DDEMLSR, проверяет только сервис (так как в нашем приложении определен только один сервис и один раздел):

Заметим, что мы сравниваем не строки, содержащие имя сервиса, а идентификаторы, так как для одинаковых строк в данном случае будут созданы одинаковые идентификаторы.

В случае успешного создания канала сервер получает от системы DDEML транзакцию с кодом XTYP_CONNECT_CONFIRM. При обработке этой транзакции сервер может сохранить идентификатор созданного канала (который передается функции обратного вызова через параметр hConv) для дальнейшего использования.

Приведем назначение параметров функции обратного вызова для транзакции XTYP_CONNECT_CONFIRM:

ПараметрЗначение
hsz1Идентификатор строки, содержащей имя раздела
hsz2Идентификатор строки, содержащей имя сервиса
dwData2Если значение равно TRUE, данная копия приложения является одновременно и клиентом, и сервером. Если же значение равно FALSE, клиент и сервер являются разными приложениями или разными копиями приложения

Когда канал связи больше не нужен, клиент или сервер может уничтожить его, вызвав функцию DdeDisconnect:

В качестве единственного параметра этой функции передается идентификатор уничтожаемого канала.

В процессе удаления канала «партнер» приложения, выступившего инициатором удаления канала, получает транзакцию XTYP_DISCONNECT. Соответствующий обработчик может при необходимости выполнить действия по освобождению ресурсов, заказанных приложением для работы с данным каналом связи.

Приложение DDEMLSR обрабатывает транзакцию XTYP_DISCONNECT следующим образом:

3.3. Передача данных через канал DDEML

Итак, мы создали канал связи между сервером и клиентом. И сервер, и клиент получили и сохранили идентификаторы созданного канала связи. Теперь все готово для того чтобы приступить к передаче данных.

Передача и прием данных может выполняться в трех режимах: по явному запросу, через «теплый» канал, или через «горячий» канал.

В первом случае клиент посылает серверу запрос, указав нужный элемент данных. Сервер, получив такой запрос, предоставляет клиенту нужные данные. «Теплый» и «горячий» каналы связи создаются в тех случаях, когда клиент должен постоянно следить за изменениями данных, хранящихся в памяти сервера.

В «теплом» режиме при изменении данных сервер посылает клиенту соответствующее извещение. Получив такое извещение, клиент запрашивает у сервера новые данные.

В «горячем» режиме при изменении данных сервер самостоятельно посылает клиенту данные без дополнительного запроса.

Процесс передачи данных заключается в посылке транзакций. Отметим, что транзакции бывают синхронные и асинхронные.

Клиент, пославший синхронную транзакцию, дожидается ее завершения в течение заданного интервала времени. Если по истечении этого интервала времени транзакция не завершилась, клиент получает код ошибки.

После посылки асинхронной транзакции клиент не ждет завершения транзакции. Когда транзакция будет завершена, клиент получит от системы DDEML транзакцию XTYP_XACT_COMPLETE.

В наших примерах мы будем работать с синхронными транзакциями.

Запрос данных от сервера

Для того чтобы получить данные от сервера, клиент должен послать серверу транзакцию XTYP_REQUEST. Задача посылки серверу транзакции решается с помощью функции DdeClientTransaction:

Если приложение запрашивает данные у сервера, для первых двух параметров следует указать нулевые значения (так как клиент не передает данные серверу, а наоборот, запрашивает их).

Через параметр hConv следует передать идентификатор созданного ранее канала связи.

Так как по одному каналу связи можно передавать различные элементы данных, следует указать нужный элемент данных с помощью параметра hszItem.

Формат данных передается через параметр uFmt. Здесь вы можете использовать один из идентификаторов формата Clipboard, такой как CF_TEXT или CF_BITMAP, в зависимости от того, что собой представляют передаваемые данные.

Через параметр uType следует передать код транзакции, посылаемой серверу. Для запроса данных следует послать транзакцию XTYP_REQUEST.

Параметр dwTimeout задает для синхронных транзакций время ожидания завершения транзакции (в миллисекундах). Вы можете указать для этого параметра значение TIMEOUT_ASYNC, в этом случае будет запущена асинхронная транзакция.

Параметр pdwResult должен содержать указатель на двойное слово. В это слово будет записан код результата выполнения транзакции. Если проверка не используется, через этот параметр можно передать нулевое значение.

Приведем фрагмент кода приложения DDEMLCL, в котором выполняется запрос данных от сервера:

В случае успешного завершения транзакции XTYP_REQUEST функция DdeClientTransaction возвращает идентификатор области глобальной памяти, в которой расположены полученные данные.

Приложение должно переписать эти данные в свой буфер, вызвав для этого функцию DdeGetData:

Последний параметр указывает смещение внутри области глобальной памяти, начиная с которого выполняется копирование. В нашем примере смещение равно нулю.

Теперь посмотрим на сервер. Получив от клиента транзакцию XTYP_REQUEST, он должен передать данные клиенту.

Приведем назначение параметров функции обратного вызова (сторона сервера) для транзакции XTYP_REQUEST:

ПараметрЗначение
hsz1Идентификатор строки, содержащей имя раздела
hsz2Идентификатор строки, содержащей имя сервиса

Возможный вариант обработчика транзакции XTYP_REQUEST показан в следующем фрагменте кода, взятом из нашего приложения DDEMLSR:

Этот фрагмент передает клиенту текстовую строку szDDEServerVersion.

Однако вначале сервер должен заказать блок глобальной памяти, записав туда передаваемые данные. Это необходимо сделать при помощи функции DdeCreateDataHandle:

Если с помощью функции DdeCreateDataHandle вы заказываете блок памяти, идентификатор которого будет возвращен функцией обратного вызова, последний параметр следует указать как NULL. В этом случае система DDEML освободит блок памяти самостоятельно, как только в нем отпадет потребность.

Итак, при обработке транзакции XTYP_REQUEST функция обратного вызова сервера создала блок глобальной памяти и записала туда передаваемые данные. Затем она должна возвратить идентификатор созданного блока памяти или NULL, если блок памяти создать невозможно.

Передача данных серверу

Процедура передачи данных состоит из двух шагов. Вначале надо создать блок глобальной памяти и записать в него передаваемые данные. Для этого следует воспользоваться только что рассмотренной нами функцией DdeCreateDataHandle:

Затем клиент должен передать серверу транзакцию XTYP_POKE, вызвав для этого функцию DdeClientTransaction:

Приведем описание параметров для транзакции XTYP_POKE:

ПараметрЗначение
hsz1Идентификатор строки, содержащей имя раздела
hsz2Идентификатор строки, содержащей имя сервиса
hDataИдентификатор данных, передаваемых серверу

Обработчик транзакции XTYP_POKE в приложении DDEMLSR выглядит следующим образом:

Этот обработчик сначала проверяет идентификатор элемента данных, затем получает данные с помощью рассмотренной нами ранее функции DdeGetData. Полученные данные отображаются на экране при помощи функции MessageBox.

Обратите внимание, что в качестве признака успешного завершения транзакции возвращается значение DDE_FACK, определенное в файле ddeml.h.

Выполнение команды

Помимо передачи данных возможно такое взаимодействие между клиентом и сервером, когда клиент передает серверу команды в виде текстовой строки, а сервер их исполняет. Вообще говоря, этот механизм можно реализовать с помощью рассмотренных нами ранее транзакций XTYP_POKE и XTYP_REQUEST, однако существует специально предназначенная для передачи команд транзакция XTYP_EXECUTE. Вот соответствующие параметры, передаваемые функции обратного вызова:

ПараметрЗначение
hsz1Идентификатор строки, содержащей имя раздела
hsz2Идентификатор строки, содержащей имя сервиса

Процесс передачи команды очень напоминает процесс передачи данных серверу через транзакцию XTYP_POKE.

Вначале необходимо при помощи функции DdeCreateDataHandle создать блок памяти, содержащей текстовую строку команды. Отличие заключается в том, что параметр hszItem должен быть указан как NULL:

Затем с помощью функции DdeClientTransaction серверу посылается транзакция XTYP_EXECUTE:

Для того чтобы получить доступ к командной строке, обработчик транзакции XTYP_EXECUTE, расположенный в функции обратного вызова сервера, должен использовать функцию DdeAccessData:

Эта функция возвращает указатель на начало области памяти, содержащей команду.

После успешного выполнения команды функция обратного вызова сервера должна вернуть значение DDE_FACK. Если команда не поддерживается, нужно вернуть значение DDE_FNOTPROCESSED. В том случае, когда сервер может выполнить команду позже (потому что занят, например, выполнением другой команды), функция обратного вызова должна вернуть значение DDE_FBUSY.

Клиент может проверить результат выполнения передачи команды, если проанализирует содержимое двойного слова, на которое указывал параметр lpdwResult перед вызовом функции DdeClientTransaction. Например, если в этом слове установлен бит DDE_FBUSY, можно попробовать повторить посылку команды позже.

3.4. Приложение DDEMLSR

Приложение DDEMLSR (рис. 3.5) регистрирует сервис «BMPServer». Клиент может установить канал связи с разделом «BMPFile» и работать с элементом данных «DDEData».

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Рис. 3.5. Приложение DDEMLSR

Функции, выполняемые сервером, предельно просты.

Когда сервер получает запрос на передачу данных клиенту, он в ответ передает текстовую строку, в которой находится описание версии приложения DDEMLSR.

Если клиент посылает серверу данные (в виде текстовой строки), сервер отображает данные на экране при помощи функции MessageBox (рис. 3.6).

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Рис. 3.6. Сервер отображает текстовую строку, полученную от клиента по каналу DDE

Функция WinMain и функция главного окна приложения определены в файле ddemlsr.cpp (листинг 3.1).

Листинг 3.1. Файл ddeml/ddemlsr.cpp

Для того чтобы скрыть главное окно приложения (а точнее, не показывать его вовсе), достаточно убрать вызов функции ShowWindow перед запуском цикла обработки сообщений. Разумеется, для стиля окна в этом случае не следует использовать значение WS_VISIBLE.

При создании главного окна приложения обработчик сообщения WM_CREATE инициализирует сервер, вызывая функцию DDEServerOpen, определенную в файле ddemlfn.cpp (листинг 3.2). Функции передается имена сервиса, раздела данных и элемента данных.

Обработчики сообщений от меню предназначены для просмотра версии сервера и завершения работы приложения. Эти действия выполняются обычным образом.

При завершении работы приложения обработчик сообщения WM_DESTROY закрывает канал DDEML и освобождает все занятые ресурсы, вызывая функцию DDEServerClose, определенную в файле ddemlfn.cpp.

Для удобства мы собрали все функции, имеющие отношение к DDEML, в файле ddemlfn.cpp. Там же определена и функция обратного вызова для сервера DDEML.

Листинг 3.2. Файл ddeml/ddemlfn.cpp

Транзакция XTYP_ERROR передается в функцию обратного вызова в случае возникновения ошибки. Младшее слово параметра dwData1 содержит код ошибки.

Файл ddemlsr.hpp (листинг 3.3) содержит определения констант для приложения DDEMLSR.

Листинг 3.3. Файл ddeml/ddemlsr.hpp

В файле определения ресурсов (листинг 3.4) описано главное меню приложения и пиктограмма.

Листинг 3.4. Файл ddeml/ddemlsr.rc

Файл определения модуля приложения DDEMLSR приведен в листинге 3.5.

Листинг 3.5. Файл ddeml/ddemlsr.def

3.5. Приложение DDEMLCL

Приложение DDEMLCL создано нами специально для работы с сервером DDEMLSR, описанном в предыдущем разделе. Вы можете запустить сервер перед запуском клиента DDEMLCL, либо не делать этого. В последнем случае на экране появится предупреждающее сообщение о том, что сервер не запущен (рис. 3.7).

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Рис. 3.7. Запрос на запуск сервера DDEML

Вам будет предложено запустить сервер, для чего следует нажать на клавишу «Yes». Приложение DDEMLCL предпримет попытку запустить приложение DDEMLSR из текущего каталога или из каталогов, указанных в переменной среды PATH операционной системы MS-DOS.

Главное окно приложения представлено на рис. 3.8.

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Рис. 3.8. Приложение DDEMLCL

С помощью меню «Action» вы можете послать серверу текстовую строку «c:\\nicebmp\\sky.bmp» (строка «Send Filename») или запросить версию сервера (строка «Get Server Version»). В последнем случае принятая строка будет отображена на экране (рис. 3.9).

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Рис. 3.9. Клиент отображает текстовую строку, полученную от сервера

Функция WinMain и функция главного окна приложения DDEMLCL определены в файле ddemlcl.cpp (листинг 3.6).

Листинг 3.6. Файл ddeml/ddemlcl.cpp

Обработчик сообщения WM_CREATE при инициализации главного окна приложения вызывает функцию DDEClientOpen, определенную в файле ddemlcf.cpp (листинг 3.7). Эта функция регистрирует приложение в библиотеке DDEML и пытается создать канал связи с сервером.

Если канал связи создать не удалось, приложение DDEMLCL делает вывод о том, что сервер не запущен, и предлагает пользователю запустить его. Запуск выполняется при помощи функции WinExec. После удачного запуска сервера делается еще одна попытка создать канал связи.

Когда пользователь выбирает из меню «Action» строку «Send Filename», приложение вызывает функцию DDESend, определенную в файле ddemlcf.cpp. Этой функции передается идентификатор созданного канала связи и текстовая строка «c:\\nicebmp\\sky.bmp». Функция DDESend передаст строку серверу, который отобразит ее на экране.

Если пользователь выбирает из меню «Action» строку «Get Server Version», вызывается функция DDEReceive, также определенная в файле ddemlcf.cpp. Этой функции помимо идентификатора канала связи передается адрес и размер буфера, в который нужно записать принятую информацию. После приема данные отображаются на экране в виде текстовой строки с помощью функции MessageBox.

Когда приложение DDEMLCL завершает свою работу, вызывается функция DDEClientClose, закрывающая канал и освобождающая связанные с ним ресурсы.

В файле ddemlcf.cpp (листинг 3.7) собраны все функции, имеющие отношение к DDEML.

Листинг 3.7. Файл ddeml/ddemlcf.cpp

Все символические константы определены в файле ddemlcf.hpp (листинг 3.8).

Листинг 3.8. Файл ddeml/ddemlcf.hpp

Файл описания ресурсов представлен в листинге 3.9.

Листинг 3.9. Файл ddeml/ddemlcf.rc

Файл определения модуля для приложения DDEMLCL вы найдете в листинге 3.10.

Листинг 3.10. Файл ddeml/ddemlcf.def

3.6. Отладка DDEML-приложений

Библиотека DDEML позволяет создавать приложения, предназначенные для отладки DDEML-приложений. В частности, такие приложения могут перехватывать вызовы функций обратного вызова DDEML (как для сервера, так и для клиента), следить за использованием идентификаторов строк и данных, за регистрацией сервиса и так далее. Из-за ограниченного объема книги мы не сможем рассказать вам о том, как создавать такие приложения, однако вся необходимая информация есть в документации, которая входит в состав Microsoft SDK for Windows 3.1.

Тем не менее, мы научим вас пользоваться готовым приложением DDESpy, которое поставляется в составе SDK и специально предназначено для отладки DDEML-приложений.

Запустите приложение DDESpy и раскройте меню «Output» (рис. 3.10).

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Рис. 3.10. Меню «Output» приложения DDESpy

С помощью этого меню вы можете направить поток отладочной информации в файл (строка «File. «), на отладочный терминал (строка «Debug Terminal» или в окно приложения DDESpy (строка «Screen»). Кроме того, с помощью строки «Clear Screen» вы можете очистить содержимое окна приложения DDESpy от отладочной информации (если она там есть).

В меню «Output» вам надо выбрать строку «File. » и с помощью появившейся на экране диалоговой панели задать путь к файлу, в который будет записана отладочная информация.

Затем раскройте меню «Monitor» (рис. 3.11).

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Рис. 3.11. Меню «Monitor» приложения DDESpy

С помощью этого меню вы можете определить состав отладочной информации, отображаемой в окне приложения и сохраняемой в только что указанном вами файле. Отметьте все строки, как на рис. 3.11. Теперь вы сможете получить полную отладочную информацию.

Затем раскройте меню «Track» (рис. 3.12).

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Рис. 3.12. Меню «Track» приложения DDESpy

С помощью этого меню вы сможете задать информацию о системе DDEML, отображаемую в отдельных окнах.

Отметьте все строки в меню «Track». При этом в нижней части экрана монитора появится несколько новых пиктограмм, соответствующих отдельным окнам.

Теперь все готово к отладке.

Запустите приложение DDEMLSR, описанное нами раньше. В главном окне приложения DDESpy появятся текстовые строки описания происходящих событий. Эти строки одновременно записываются в файл, указанный нами ранее. Мы к ним еще вернемся, а пока давайте раскроем пиктограмму «Registered Service». Появится окно, в котором вы сможете увидеть имя сервиса «BMPServer», а также название и идентификатор копии приложения (рис. 3.13).

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Рис. 3.13. Список серверов DDEML

Раскройте окно «Active Conversation», в котором отображается информация об активных каналах связи.

В этот момент времени ни один канал связи еще не создан, поэтому окно пустое. Запустите приложение DDEMLCL, предназначенное для совместной работы с приложением DDEMLSR. Оно создаст канал связи, используя сервис «BMPServer» и раздел «BMPFile». Теперь в окне «Active Conversation» есть информация о сервисе, разделе и идентификаторах копий приложений клиента и сервера, создавшего канал связи (рис. 3.14).

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Рис. 3.14. Список активных каналов

Итак, канал связи установлен. Раскройте окно «String Handles», отображающее список созданных идентификаторов строк (рис. 3.15).

Что такое динамический обмен данными. Смотреть фото Что такое динамический обмен данными. Смотреть картинку Что такое динамический обмен данными. Картинка про Что такое динамический обмен данными. Фото Что такое динамический обмен данными

Рис. 3.15. Список идентификаторов строк

Сделайте активным окно клиента DDEMLCL и выполните пересылку данных, выбрав из меню «Action» строки «Send Filename» и затем «Get Server Version». Будет выполнена передача данных по каналу связи, причем информация о результате будет записана в отладочный файл.

Закройте приложение DDEMLCL и сделайте активным окно «String Handles». Теперь счетчик использования всех трех идентификаторов строк будет равен 1, так как клиент освободил эти идентификаторы. Однако сервер продолжает их использовать, поэтому идентификаторы не уничтожаются.

Окно «Active Conversation» очистится, так как теперь в системе нет активных каналов связи (если только их не создали какие-либо другие приложения).

Теперь завершите приложение DDEMLSR. Окна «String Handles» и «Registered Service» теперь тоже очистятся, так как все строки уничтожены, а сервис больше не доступен.

Завершите приложение DDESpy и загрузите в любой текстовый редактор файл, содержащий протокол отладки. Мы приведем фрагменты такого файла, полученного в результате выполнения описанных выше манипуляций с приложениями DDEMLSR и DDEMLCL.

Первые три строки появились в результате запуска сервера DDEMLSR. Они содержат сведения о том, что были созданы три идентификатора строк для копии приложения с идентификатором 0x458f. Указано время события (от момента запуска Windows), идентификаторы созданных строк (c0d0, c0d5, c2d8) и содержимое строк.

Далее идут строки, описывающие вызов функции обратного вызова сервера:

Здесь функция обратного вызова была вызвана для выполнения регистрации сервиса «BMPServer». Вы можете определить содержимое всех параметров функции на момент вызова.

В следующем фрагмента отражен факт посылки данных серверу:

Следом идет обращение к функции обратного вызова:

А вот запрос данных от сервера:

В следующем фрагменте листинга выполняется запрос на уничтожение канала связи, после чего управление получает функция обратного вызова:

Перед завершением работы сервер должен сообщить системе DDEML, что обеспечиваемый им сервис больше не доступен. Следующий фрагмент листинга отражает процедуру «изъятия» сервиса :

Анализируя содержимое протокола отладки, вы можете проследить за тем, чтобы при завершении сервера освобождались все занимаемые им ресурсы, такие как идентификаторы строк и сервис. Вы можете проверить значения параметров функции обратного вызова для всех или отдельных транзакций, проследить формат передаваемых данных и многое другое.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *