Partager via


Recherche de systèmes hôtes de serveur

Un système hôte de serveur est l’ordinateur qui exécute le programme serveur de l’application distribuée. Il peut y avoir un ou plusieurs systèmes hôtes de serveur sur un réseau. La façon dont votre programme client trouve un serveur auquel se connecter dépend des besoins de votre programme.

Il existe deux méthodes pour rechercher des systèmes hôtes de serveur :

  • Utilisation des informations stockées dans des chaînes dans le code source du client, des variables d’environnement ou des fichiers de configuration spécifiques à l’application. Votre application cliente peut utiliser les données de la chaîne pour composer une liaison entre le client et le serveur.
  • Interrogation d’une base de données de service de noms pour l’emplacement d’un programme serveur.

Cette section présente des informations sur ces deux techniques dans les rubriques suivantes :

Utilisation de liaisons de chaînes

Les applications peuvent créer des liaisons à partir d’informations stockées dans des chaînes. Votre application cliente compose ces informations sous forme de chaîne, puis appelle la fonction RpcBindingFromStringBinding . Le client doit fournir les informations suivantes pour identifier le serveur :

(L’UUID de l’objet et les informations de point de terminaison sont facultatives.)

Dans les exemples suivants, le paramètre pszNetworkAddress et d’autres paramètres incluent des barres obliques inverses incorporées. La barre oblique inverse est un caractère d’échappement dans le langage de programmation C. Deux barres obliques inverses sont nécessaires pour représenter chaque seul caractère de barre oblique inverse littérale. La structure de liaison de chaîne doit contenir quatre caractères de barre oblique inverse pour représenter les deux caractères de barre oblique inverse littérale qui précèdent le nom du serveur.

L’exemple suivant montre que le nom du serveur doit être précédé de huit barres obliques inverses afin que quatre caractères de barre oblique inverse littéral apparaissent dans la structure de données de liaison de chaîne après que la fonction sprintf_s traite la chaîne.

/* client application */

char * pszUuid = "6B29FC40-CA47-1067-B31D-00DD010662DA";
char * pszProtocol = "ncacn_np";
char * pszNetworkAddress = "\\\\\\\\servername";
char * pszEndpoint = "\\\\pipe\\\\pipename";
char * pszString;
 
int len = 0;
 
len  = sprintf_s(pszString, strlen(pszUuid), "%s", pszUuid);
len += sprintf_s(pszString + len, strlen(pszProtocolSequence) + 2, "@%s:",
    pszProtocolSequence);
if (pszNetworkAddress != NULL)
    len += sprintf_s(pszString + len, strlen(pszNetworkAddress), "%s",
    pszNetworkAddress);
len += sprintf_s(pszString + len, strlen(pszEndpoint) + 2, "[%s]", pszEndpoint);

Dans l’exemple suivant, la liaison de chaîne s’affiche comme suit :

6B29FC40-CA47-1067-B31D-00DD010662DA@ncacn_np:\\\\nom_serveur[\\pipe\\pipename]

Le client appelle ensuite RpcBindingFromStringBinding pour obtenir le handle de liaison :

RPC_BINDING_HANDLE hBinding;
 
status = RpcBindingFromStringBinding(pszString, &hBinding);
//...

Fonction pratique, RpcStringBindingCompose assemble l’objet UUID, la séquence de protocole, l’adresse réseau et le point de terminaison dans la syntaxe appropriée pour l’appel à RpcBindingFromStringBinding. Vous n’avez pas à vous soucier de placer l’esperluette, le signe deux-points et les différents composants de chaque séquence de protocole au bon endroit; vous fournissez simplement les chaînes en tant que paramètres à la fonction . La bibliothèque d’exécution alloue même la mémoire nécessaire pour la liaison de chaîne.

char * pszNetworkAddress = "\\\\server";
char * pszEndpoint = "\\pipe\\pipename";
status = RpcStringBindingCompose(
            pszUuid,
            pszProtocolSequence,
            pszNetworkAddress,
            pszEndpoint,
            pszOptions,
            &pszString);
//...
status = RpcBindingFromStringBinding(
            pszString,
            &hBinding);
//...

Une autre fonction pratique, RpcBindingToStringBinding, prend un handle de liaison comme entrée et produit la liaison de chaîne correspondante.

Importation à partir de bases de données de service de noms

Les bases de données de service de noms stockent, entre autres, les handles de liaison et les UUID. Votre application cliente peut rechercher l’un ou l’autre de ces éléments lorsqu’elle doit se lier au serveur. Pour obtenir une présentation des informations qu’un service de noms stocke et du format de stockage, consultez La base de données du service de noms RPC.

La bibliothèque RPC fournit deux ensembles de fonctions que votre programme client peut utiliser pour rechercher dans la base de données du service de noms. Les noms d’un jeu commencent par RpcNsBindingImport. Les noms de l’autre jeu commencent par RpcNsBindingLookup. La différence entre les deux groupes de fonctions est que les fonctions RpcNsBindingImport retournent un seul handle de liaison par appel et que les fonctions RpcNsBindingLookup retournent des groupes de handles par appel.

Pour commencer une recherche avec les fonctions RpcNsBindingImport, appelez d’abord RpcNsBindingImportBegin, comme indiqué dans le fragment de code suivant.

RPC_STATUS status;
RPC_NS_HANDLE hNameServiceHandle;
 
status = RpcNsBindingImportBegin(
    RPC_C_NS_SYNTAX_DEFAULT,
    NULL,
    MyInterface_v1_0_c_ifspec,
    NULL,
    &hNameServiceHandle);

Lorsque les fonctions RPC effectuent une recherche dans la base de données du service de noms, elles ont besoin d’un emplacement pour commencer la recherche. Dans la terminologie RPC, il s’agit du nom d’entrée. Votre programme client transmet le nom d’entrée comme deuxième paramètre à RpcNsBindingImportBegin. Ce paramètre peut avoir la valeur NULL si vous souhaitez rechercher l’intégralité de la base de données du service de noms. Vous pouvez également effectuer une recherche dans l’entrée du serveur en transmettant un nom d’entrée de serveur ou effectuer une recherche dans l’entrée de groupe en transmettant un nom d’entrée de groupe. Le passage d’un nom d’entrée limite la recherche au contenu de cette entrée.

Dans l’exemple précédent, la valeur RPC_C_NS_SYNTAX_DEFAULT est passée en tant que premier paramètre à RpcNsBindingImportBegin. Cette opération sélectionne la syntaxe du nom d’entrée par défaut. Actuellement, il s’agit de la seule syntaxe de nom d’entrée prise en charge.

Votre application cliente peut rechercher dans la base de données du service de noms un nom d’interface, un UUID ou les deux. Si vous souhaitez qu’il recherche une interface par son nom, transmettez la variable d’interface globale générée par le compilateur MIDL à partir de votre fichier IDL en tant que troisième paramètre à RpcNsBindingImportBegin. Vous trouverez sa déclaration dans le fichier d’en-tête que le compilateur MIDL a généré lors de la génération du stub client. Si vous souhaitez que votre programme client effectue une recherche par UUID uniquement, définissez le troisième paramètre sur NULL.

Lorsque vous recherchez un UUID dans la base de données de service de noms, définissez le quatrième paramètre de RpcNsBindingImportBegin sur l’UUID que vous souhaitez rechercher. Si vous ne recherchez pas d’UUID, définissez ce paramètre sur NULL.

La fonction RpcNsBindingImportBegin transmet l’adresse d’un handle de contexte de recherche de nom par le biais de son cinquième paramètre. Vous passez ce paramètre à d’autres fonctions RpcNsBindingImport.

En particulier, la fonction suivante que votre application cliente appellerait est RpcNsBindingImportNext. Les programmes clients utilisent cette fonction pour récupérer des handles de liaison compatibles à partir de la base de données du service de noms. Le fragment de code suivant montre comment cette fonction peut être appelée :

RPC_STATUS status;
RPC_BINDING_HANDLE hBindingHandle;
// The variable hNameServiceHandle is a valid name service search 
// context handle obtained from the RpcNsBindingBegin function.
 
status = RpcNsBindingImportNext(hNameServiceHandle, &hBindingHandle);

Une fois qu’elle a appelé la fonction RpcNsBindingImportNext pour obtenir un handle de liaison, votre application cliente peut déterminer si le handle qu’elle a reçu est acceptable. Si ce n’est pas le cas, votre programme client peut exécuter une boucle et appeler à nouveau RpcNsBindingImportNext pour voir si le service de noms contient un handle plus approprié. Pour chaque appel à RpcNsBindingImportNext, il doit y avoir un appel correspondant à RpcNsBindingFree. Une fois votre recherche terminée, appelez la fonction RpcNsBindingImportDone pour libérer le contexte de recherche.

Une fois que votre application cliente dispose d’un handle de liaison acceptable, elle doit case activée pour s’assurer que l’application serveur est en cours d’exécution. Il existe deux méthodes que votre client peut utiliser pour effectuer cette vérification. La première consiste à appeler une fonction dans l’interface cliente. Si le programme serveur est en cours d’exécution, l’appel se termine. Si ce n’est pas le cas, l’appel échoue. Une meilleure façon de vérifier que le serveur est en cours d’exécution consiste à appeler RpcEpResolveBinding, suivi d’un appel à RpcMgmtIsServerListening. Pour plus d’informations sur la base de données du service de noms, consultez La base de données du service de noms RPC.