Condividi tramite


Applicazione client

L'esempio seguente è tratto dall'applicazione "Hello World" nella directory RPC\Hello di Platform Software Development Kit (SDK). Il file di origine Helloc.c contiene una direttiva per includere il file di intestazione generato da MIDL, Hello.h. All'interno di Hello.h sono direttive per includere Rpc.h e rpcndr.h, che contengono le definizioni per le routine di runtime RPC, HelloProc e Shutdown e i tipi di dati usati dalle applicazioni client e server. Il compilatore MIDL deve essere usato con l'esempio seguente.

Poiché il client gestisce la connessione al server, l'applicazione client chiama le funzioni di runtime per stabilire un handle per il server e rilasciare questo handle al termine delle chiamate alla procedura remota. La funzione RpcStringBindingCompose combina i componenti dell'handle di associazione in una rappresentazione di stringa di tale handle e alloca la memoria per l'associazione di stringhe. La funzione RpcBindingFromStringBinding crea un handle di associazione server , hello_ClientIfHandle, per l'applicazione client da tale rappresentazione di stringa.

Nella chiamata a RpcStringBindingCompose, i parametri non specificano l'UUID perché in questa esercitazione si presuppone che sia presente una sola implementazione dell'interfaccia "hello". Inoltre, la chiamata non specifica un indirizzo di rete perché l'applicazione userà l'impostazione predefinita, ovvero il computer host locale. La sequenza di protocollo è una stringa di caratteri che rappresenta il trasporto di rete sottostante. L'endpoint è un nome specifico della sequenza di protocollo. Questo esempio usa named pipe per il trasporto di rete, quindi la sequenza di protocollo è "ncacn_np". Il nome dell'endpoint è "\pipe\hello".

Le chiamate di procedura remota effettive, HelloProc e Shutdown, vengono eseguite all'interno del gestore di eccezioni RPC, ovvero un set di macro che consentono di controllare le eccezioni che si verificano al di fuori del codice dell'applicazione. Se il modulo RPC runtime segnala un'eccezione, il controllo passa al blocco RpcExcept . In questo caso si inserisce il codice per eseguire le operazioni di pulizia necessarie e quindi uscire normalmente. Questo programma di esempio informa semplicemente l'utente che si è verificata un'eccezione. Se non si desidera utilizzare le eccezioni, è possibile utilizzare gli attributi ACF comm_status e fault_status per segnalare gli errori.

Al termine delle chiamate di procedura remota, il client chiama prima RpcStringFree per liberare la memoria allocata per l'associazione di stringhe. Si noti che dopo aver creato l'handle di associazione, un programma client può liberare un'associazione di stringhe in qualsiasi momento. Il client chiama quindi RpcBindingFree per rilasciare l'handle.

/* 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);
}