Поделиться через


Клиентское приложение

Приведенный ниже пример получен из приложения "Hello World" в каталоге RPC\Hello пакета средств разработки программного обеспечения платформы (SDK). Исходный файл Helloc.c содержит директиву для включения созданного MIDL файла заголовка Hello.h. В Hello.h находятся директивы для включения Rpc.h и rpcndr.h, которые содержат определения для подпрограмм времени выполнения RPC, HelloProc и Shutdown, а также типы данных, используемые клиентскими и серверными приложениями. Компилятор MIDL необходимо использовать в приведенном ниже примере.

Так как клиент управляет подключением к серверу, клиентское приложение вызывает функции времени выполнения, чтобы установить дескриптор для сервера и освободить этот дескриптор после завершения вызовов удаленных процедур. Функция RpcStringBindingCompose объединяет компоненты дескриптора привязки в строковое представление этого дескриптора и выделяет память для привязки строки. Функция RpcBindingFromStringBinding создает дескриптор привязки сервера , hello_ClientIfHandle, для клиентского приложения из этого строкового представления.

В вызове RpcStringBindingCompose параметры не указывают UUID, так как в этом руководстве предполагается, что существует только одна реализация интерфейса hello. Кроме того, в вызове не указан сетевой адрес, так как приложение будет использовать значение по умолчанию, которое является локальным хост-компьютером. Последовательность протокола — это строка символов, представляющая базовый сетевой транспорт. Конечная точка — это имя, которое зависит от последовательности протокола. В этом примере для сетевого транспорта используются именованные каналы, поэтому последовательность протокола — "ncacn_np". Имя конечной точки — \pipe\hello.

Фактические удаленные вызовы процедур HelloProc и Shutdown выполняются в обработчике исключений RPC — наборе макросов, которые позволяют управлять исключениями, происходящими за пределами кода приложения. Если модуль среды выполнения RPC сообщает об исключении, управление передается блоку RpcExcept . Здесь можно вставить код для выполнения любой необходимой очистки, а затем корректно завершить работу. Этот пример программы просто информирует пользователя о том, что произошло исключение. Если вы не хотите использовать исключения, можно использовать атрибуты ACF comm_status и fault_status для сообщения об ошибках.

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

/* file: helloc.c */
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "hello.h" 
#include <windows.h>

void main()
{
    RPC_STATUS status;
    unsigned char * pszUuid             = NULL;
    unsigned char * pszProtocolSequence = "ncacn_np";
    unsigned char * pszNetworkAddress   = NULL;
    unsigned char * pszEndpoint         = "\\pipe\\hello";
    unsigned char * pszOptions          = NULL;
    unsigned char * pszStringBinding    = NULL;
    unsigned char * pszString           = "hello, world";
    unsigned long ulCode;
 
    status = RpcStringBindingCompose(pszUuid,
                                     pszProtocolSequence,
                                     pszNetworkAddress,
                                     pszEndpoint,
                                     pszOptions,
                                     &pszStringBinding);
    if (status) exit(status);

    status = RpcBindingFromStringBinding(pszStringBinding, &hello_ClientIfHandle);
 
    if (status) exit(status);
 
    RpcTryExcept  
    {
        HelloProc(pszString);
        Shutdown();
    }
    RpcExcept(1) 
    {
        ulCode = RpcExceptionCode();
        printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
    }
    RpcEndExcept
 
    status = RpcStringFree(&pszStringBinding); 
 
    if (status) exit(status);
 
    status = RpcBindingFree(&hello_IfHandle);
 
    if (status) exit(status);

    exit(0);
}

/******************************************************/
/*         MIDL allocate and free                     */
/******************************************************/
 
void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
{
    return(malloc(len));
}
 
void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
{
    free(ptr);
}