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


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

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

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

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

Фактические вызовы удаленных процедур, HelloProc и завершение работы, выполняются в обработчике исключений 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);
}