L'application cliente
L’exemple ci-dessous provient de l’application « Hello World » dans le répertoire RPC\Hello du Kit de développement logiciel (SDK) de plateforme. Le fichier source Helloc.c contient une directive pour inclure le fichier d’en-tête généré par MIDL, Hello.h. Dans Hello.h sont des directives pour inclure Rpc.h et rpcndr.h, qui contiennent les définitions des routines d’exécution RPC, HelloProc et Shutdown, ainsi que les types de données utilisés par les applications clientes et serveurs. Le compilateur MIDL doit être utilisé avec l’exemple ci-dessous.
Étant donné que le client gère sa connexion au serveur, l’application cliente appelle les fonctions d’exécution pour établir un handle au serveur et pour libérer ce handle une fois les appels de procédure distante terminés. La fonction RpcStringBindingCompose combine les composants du handle de liaison dans une représentation sous forme de chaîne de ce handle et alloue de la mémoire pour la liaison de chaîne. La fonction RpcBindingFromStringBinding crée un handle de liaison de serveur, hello_ClientIfHandle, pour l’application cliente à partir de cette représentation sous forme de chaîne.
Dans l’appel à RpcStringBindingCompose, les paramètres ne spécifient pas l’UUID, car ce tutoriel suppose qu’il n’existe qu’une seule implémentation de l’interface « hello ». En outre, l’appel ne spécifie pas d’adresse réseau, car l’application utilisera la valeur par défaut, qui est l’ordinateur hôte local. La séquence de protocole est une chaîne de caractères qui représente le transport réseau sous-jacent. Le point de terminaison est un nom spécifique à la séquence de protocole. Cet exemple utilise des canaux nommés pour son transport réseau, de sorte que la séquence de protocole est « ncacn_np ». Le nom du point de terminaison est « \pipe\hello ».
Les appels de procédure distante réels, HelloProc et Shutdown, ont lieu dans le gestionnaire d’exceptions RPC, un ensemble de macros qui vous permettent de contrôler les exceptions qui se produisent en dehors du code de l’application. Si le module d’exécution RPC signale une exception, le contrôle passe au bloc RpcExcept . C’est là que vous devez insérer du code pour effectuer tout nettoyage nécessaire, puis quitter correctement. Cet exemple de programme informe simplement l’utilisateur qu’une exception s’est produite. Si vous ne souhaitez pas utiliser d’exceptions, vous pouvez utiliser les attributs ACF comm_status et fault_status pour signaler des erreurs.
Une fois les appels de procédure distante terminés, le client appelle d’abord RpcStringFree pour libérer la mémoire allouée à la liaison de chaîne. Notez qu’une fois le handle de liaison créé, un programme client peut libérer une liaison de chaîne à tout moment. Le client appelle ensuite RpcBindingFree pour libérer le 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);
}