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

       

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


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

HDDEDATA WINAPI DdeClientTransaction( void FAR* pData, // адрес данных, передаваемых серверу DWORD cbData, // размер передаваемых данных HCONV hConv, // идентификатор канала HSZ hszItem, // идентификатор элемента данных UINT uFmt, // формат данных UINT uType, // код транзакции DWORD dwTimeout, // продолжительность периода ожидания DWORD FAR* pdwResult); // указатель на двойное слово, // в которое будет записан результат выполнения транзакции

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

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

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

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

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

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

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

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

hData = DdeClientTransaction(NULL, 0, hConv, hszItem, CF_TEXT, XTYP_REQUEST, 1000, &dwResult); if(hData != NULL) { DdeGetData(hData, szBuf, nBufSize, 0L); return TRUE; }






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

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

DWORD WINAPI DdeGetData( HDDEDATA hData, // идентификатор области памяти void FAR* pDst, // адрес буфера DWORD cbMax, // размер буфера DWORD cbOff); // смещение начала данных

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

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

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

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

case XTYP_REQUEST: { // Создаем идентификатор данных hData = DdeCreateDataHandle(idInst, szDDEServerVersion, lstrlen(szDDEServerVersion) + 1, 0L, hszItem, CF_TEXT, 0);

// В случае успеха возвращаем созданный идентификатор if(hData != NULL) return(hData); else return(NULL); }

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

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

HDDEDATA WINAPI DdeCreateDataHandle( DWORD idInst, // идентификатор приложения void FAR* pSrc, // адрес буфера DWORD cb, // размер буфера DWORD cbOff, // смещение начала данных HSZ hszItem, // идентификатор элемента данных UINT wFmt, // формат данных UINT afCmd); // флаги

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

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


Содержание раздела