Condividi tramite


Sviluppo client tramite handle di contesto

L'unico uso di un programma client per un handle di contesto consiste nel passarlo al server ogni volta che il client effettua una chiamata di procedura remota. L'applicazione client non deve accedere al contenuto dell'handle. Non dovrebbe provare a modificare i dati di gestione del contesto in alcun modo. Le procedure remote richiamate dal client eseguono tutte le operazioni necessarie nel contesto del server.

Prima di richiedere un handle di contesto da un server, i client devono stabilire un'associazione con il server. Il client può usare un handle di associazione automatico, implicito o esplicito. Con un handle di associazione valido, il client può chiamare una procedura remota nel server che restituisce un handle di contesto aperto (non NULL) o ne passa uno tramite un parametro [out] nell'elenco dei parametri della routine remota.

I client possono usare handle di contesto aperti in qualsiasi modo necessari. Tuttavia, dovrebbero invalidare l'handle quando non ne hanno più bisogno. È possibile eseguire questa operazione in due modi:

  • Per richiamare una procedura remota offerta dal programma server che libera il contesto e chiude l'handle di contesto (impostalo su NULL).
  • Quando il server non è raggiungibile, chiamare la funzione RpcSsDestroyClientContext .

Il secondo approccio pulisce solo lo stato lato client e non pulisce lo stato lato server, quindi deve essere usato solo quando la partizione di rete è sospetta e il client e il server eseguirà una pulizia indipendente. Il server esegue la pulizia indipendente tramite la routine di run-down, il client usa la funzione RpcSsDestroyClientContext .

Il frammento di codice seguente presenta un esempio di come un client potrebbe usare un handle di contesto. Per visualizzare la definizione dell'interfaccia usata in questo esempio, vedere Sviluppo interfaccia tramite handle di contesto. Per l'implementazione del server, vedere Sviluppo server tramite handle di contesto.

In questo esempio il client chiama RemoteOpen per ottenere un handle di contesto contenente dati validi. Il client può quindi usare l'handle di contesto nelle chiamate di routine remote. Poiché non necessita più dell'handle di associazione, il client può liberare l'handle esplicito usato per creare l'handle di contesto:

// cxhndlc.c  (fragment of client side application)
printf("Calling the remote procedure RemoteOpen\n");
if (RemoteOpen(&phContext, pszFileName) < 0) 
{
    printf("Unable to open %s\n", pszFileName);
    Shutdown();
    exit(2);
}
 
// Now the context handle also manages the binding.
// The variable hBindingHandle is a valid binding handle.
status = RpcBindingFree(&hBindingHandle);
printf("RpcBindingFree returned 0x%x\n", status);
if (status) 
    exit(status);

L'applicazione client in questo esempio usa una procedura denominata RemoteRead per leggere un file di dati nel server finché non rileva una fine del file. Chiude quindi il file chiamando RemoteClose. L'handle di contesto viene visualizzato come parametro nelle funzioni RemoteRead e RemoteClose come:

printf("Calling the remote procedure RemoteRead\n");
do 
{
    cbRead = 1024; // Using a 1K buffer
    RemoteRead(phContext, pbBuf, &cbRead);
    // cbRead contains the number of bytes actually read.
    for (int i = 0; i < cbRead; i++)
        putchar(*(pbBuf+i));
} while(cbRead);
 
printf("Calling the remote procedure RemoteClose\n");
if (RemoteClose(&phContext) < 0 ) 
{
    printf("Close failed on %s\n", pszFileName);
    exit(2);
}