DDE, начало обмена и его завершение
Когда мы говорили об общем виде протокола DDE, мы отметили, что он основан на обмене сообщениями. В большинстве случаев сообщения посылаются (post) а не передаются (send). При этом приложение, посылающее сообщение не имеет возможности дождаться обработки этого сообщения. Поэтому те данные, которые посылаются одним приложением, должны быть уничтожены другим, что бы они не оставались в памяти. Единственное исключение из этого правила — сообщения WM_DDE_INITIATE и ответ на него (WM_DDE_ACK) которые всегда передаются, а не посылаются. При начале DDE–разговора посылается сообщение WM_DDE_INITIATE hWnd aTopic & aService это сообщение используется для начала DDE–разговора. Параметр wParam содержит хендл пославшего окна, а lParam в младшем слове — атом aService, а в старшем — атом aTopic, задающие, соответственно, сервис и тему DDE–разговора. Нулевые значения атомов указывают соответственно на любую поддерживаемую тему и любой сервис. Передача: Когда клиент вызывает функцию SendMessage для установления DDE–разговора, он создает необходимые атомы, а после возврата из функции SendMessage он обязан эти атомы удалить. Получение: сервер, получивший это сообщение, и поддерживающий указанные сервис и тему отвечает сообщением WM_DDE_ACK. При этом он обязан создать заново требуемые атомы — использовать атомы, полученные с сообщением запрещено. Значения атомов aTopic и aService равные 0 указывают, соответственно, на любую поддерживаемую сервером тему и сервис. В этом случае сервер должен ответить столько раз, сколько подходящих тем и сервисов он поддерживает. Это сообщение передается всем приложениям (в качестве хендла окна–получателя сообщения используется HWND_BROADCAST или -1). Тот сервер, который поддерживает данную тему и сервис должен ответить на этот запрос передачей сообщения
WM_DDE_ACK hWnd aTopic & aService сообщение, подтверждающее принятое прежде сообщение. Параметр wParam содержит хендл пославшего окна, а lParam используется разными способами, в зависимости от того, какое сообщение вызвало это подтверждение. В зависимости от значений параметров сообщения рассматривают положительные и отрицательные подтверждения. При ответе на WM_DDE_INITIATE младшее слово lParam содержит атом сервиса, а старшее — атом темы, при этом WM_DDE_ACK не посылается, а передается с помощью функции SendMessage, причем оно рассматривается только как положительное, так как в качестве отрицательного ответа используется отсутствие этого сообщения. Если WM_DDE_ACK получено в ответ на WM_DDE_INITIATE, то для обоих платформ — Windows 3.x и Win32 оно используется одинаково; а если оно получено в ответ на какое–либо иное сообщение, то параметр lParam будет использован для передачи “упакованного” значения. Получение: приложение–клиент, получившее сообщение WM_DDE_ACK обязано удалить все сопровождающие его атомы. Передача: при ответе на WM_DDE_INITIATE запрещено использовать полученные атомы, сервер обязан создать необходимые для ответа атомы и послать их (так как на одно WM_DDE_INITIATE может ответить несколько серверов, а при обработке WM_DDE_ACK клиент обязан удалять все атомы). Если WM_DDE_ACK передается в ответ на сообщение WM_DDE_INITIATE, то в lParam содержатся такие–же данные, что и у сообщения WM_DDE_INITIATE. Это считается положительным подтверждением. Если ответ отрицательный, то подтверждение при инициализации просто не выдается. В большинстве случаев сервер, отвечающий на WM_DDE_INITIATE, создает специальное окно для каждого DDE–разговора. Это связано с тем, что при дальнейшем обмене данными сервис и тема указываться не будут, а сам DDE–разговор определяется фактически окном–клиентом и окном–сервером. Одна такая пара окон обменивается данными только в рамках указанных при установлении DDE–разговора темы и сервиса. Только самые простые DDE–серверы могут обходиться одним окном, но при этом они в данный момент времени могут работать только с одним клиентом.
Внимание! При установлении связи с каким–либо сервером Вы можете получить несколько сообщений WM_DDE_ACK от разных серверов, поддерживающих указанные сервис и тему. Если в сообщении WM_DDE_INITIATE вы указали любую поддерживаемую тему и/или любой возможный сервис, то практически всегда отвечают сразу несколько серверов. В этом случае Вы должны создавать список всех тем и сервисов, с которыми устанавливается связь данной операцией (не забудьте в конце закрыть все начатые DDE–разговоры), а если вы собираетесь работать только с одним из ответивших серверов, то со всеми остальными вы должны завершить DDE–разговор посылкой WM_DDE_TERMINATE. Замечание. Согласно документации сервер, получивший WM_DDE_INITIATE с указанием любой поддерживаемой темы или сервиса, обязан отправить в ответ столько сообщений WM_DDE_ACK, сколько тем и сервисов он поддерживает. На самом деле многие DDE серверы этого не делают, как, например, Microsoft Internet Explorer. Такие серверы отвечают только на точно указанные сервис и тему. Это может быть оправдано, если сервер поддерживает значительное число тем или сервисов. При ответе на WM_DDE_INITIATE уже устанавливаетя DDE–разговор, для которого сервер создает отдельное окно и, соответственно, расходует ресурсы. Если сервер отвечает на целый список тем и/или сервисов, то создается много окон, что, скорее всего, излишне. Строго говоря, указывать любую тему или сервис надо только в случае реальной необходимости, так как одним таким запросом могут быть установлены несколько десятков DDE–разговоров сразу (так, например, один только Netscape Navigator отвечает примерно 3 десятками поддерживаемых им тем).
Начало DDE–разговора - это единственный случай, когда сообщения DDE передаются с помощью SendMessage, а не PostMessage. Это необходимо для нормального начала обмена. Сейчас мы рассмотрим небольшой пример взаимодействия двух приложений, клиента и сервера при начале DDE–разговора. В данном примере рассмотрен самый простой случай, когда связь устанавливается только с одним сервером и для одной темы. При этом можно обойтись без создания списка сервисов и тем, с которыми устанавливаются соединения.
Считается, что при инициализации DDE–разговора, клиент должен получить ответ (или убедится в его отсутствии) немедленно. Этого можно достичь только используя передачу, а не посылку сообщений. В этом случае подтверждение приходит в то время, пока клиент ожидает завершения работы процедуры SendMessage. Для нормального продолжения DDE клиент должен запомнить хендл сервера (а сервер - хендл клиента). Так как возможен случай, что на запрос клиента ответят два и более серверов, то надо предусмотреть либо отказ от установления более чем одного соединения (как в приведенном примере), либо организовать DDE сразу с несколькими серверами.
Если клиент получил положительный ответ от сервера, то он может начать обмен данными. Этот обмен будет продолжаться до тех пор, пока оба приложения не обменяются сообщениями WM_DDE_TERMINATE hWnd 0L сообщение оканчивает DDE–разговор. Параметр hWnd является хендлом пославшего окна. При этом уничтожаются вспомогательные структуры и обнуляются переменные.
Послать WM_DDE_TERMINATE может как клиент, так и сервер. Оба они должны быть готовы к приему такого сообщения от напарника.
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|