Condividi tramite


Registrazione delle interfacce

Questa sezione illustra in dettaglio il processo di registrazione di un'interfaccia RPC.

Le informazioni contenute in questa sezione sono presentate negli argomenti seguenti:

Funzioni di registrazione dell'interfaccia

I server registrano le proprie interfacce chiamando la funzione RpcServerRegisterIf . I programmi server complessi supportano spesso più interfacce. Le applicazioni server devono chiamare questa funzione una volta per ogni interfaccia supportata.

Inoltre, i server possono supportare più versioni della stessa interfaccia, ognuna con la propria implementazione delle funzioni dell'interfaccia. Se il programma server esegue questa operazione, deve fornire un set di punti di ingresso. Un punto di ingresso è una routine di gestione che invia le chiamate per una versione di un'interfaccia. Deve essere presente un punto di ingresso per ogni versione dell'interfaccia. Il gruppo di punti di ingresso viene chiamato vettore del punto di ingresso. Per informazioni dettagliate, vedere Vettori di punti di ingresso.

Oltre alla funzione standard RpcServerRegisterIf, RPC supporta anche altre funzioni di registrazione dell'interfaccia. La funzione RpcServerRegisterIf2 estende le funzionalità di RpcServerRegisterIf consentendo di specificare un set di flag di registrazione (vedere Flag di registrazione interfaccia), il numero massimo di richieste di chiamata di routine remota simultanee che il server può accettare e le dimensioni massime in byte dei blocchi di dati in ingresso.

La libreria RPC contiene anche una funzione denominata RpcServerRegisterIfEx. Analogamente alla funzione RpcServerRegisterIf , questa funzione registra un'interfaccia. Il programma server può anche usare questa funzione per specificare un set di flag di registrazione (vedere Flag di registrazione interfaccia), il numero massimo di richieste di chiamata di routine remota simultanee che il server può accettare e una funzione di callback di sicurezza.

Le funzioni RpcServerRegisterIf, RpcServerRegisterIfEx e RpcServerRegisterIf2 impostano i valori nella tabella del Registro di sistema dell'interfaccia interna. Questa tabella viene usata per eseguire il mapping degli UUID dell'interfaccia e degli UUID oggetto a un gestore EPV. Il gestore EPV è una matrice di puntatori a funzione che contiene esattamente un puntatore a funzione per ogni prototipo di funzione nell'interfaccia specificata nel file IDL.

Per informazioni sulla fornitura di più EPV per fornire più implementazioni dell'interfaccia, vedere Implementazioni di più interfacce.

La libreria di runtime usa la tabella del Registro di sistema dell'interfaccia (impostata dalle chiamate alla funzione RpcServerRegisterIf, RpcServerRegisterIfEx o RpcServerRegisterIf2) e la tabella del Registro di sistema degli oggetti (impostata dalle chiamate alla funzione RpcObjectSetType) per eseguire il mapping degli UUID dell'interfaccia e dell'oggetto al puntatore a funzione.

Quando si vuole che il programma server rimuova un'interfaccia dal Registro di sistema della libreria di runtime RPC, chiamare la funzione RpcServerUnregisterIf . Dopo la rimozione dell'interfaccia dal Registro di sistema, la libreria di runtime RPC non accetterà più nuove chiamate per tale interfaccia.

Vettori del punto di ingresso

Il vettore del punto di ingresso del gestore (EPV) è una matrice di puntatori a funzione che puntano alle implementazioni delle funzioni specificate nel file IDL. Il numero di elementi nella matrice corrisponde al numero di funzioni specificate nel file IDL. RPC supporta più vettori di punto di ingresso che rappresentano più implementazioni delle funzioni specificate nell'interfaccia.

Il compilatore MIDL genera automaticamente un tipo di dati EPV di gestione da usare nella costruzione di EPV di gestione. Il tipo di dati è denominato if-name**_SERVER_EPV**, dove if-name specifica l'identificatore di interfaccia nel file IDL.

Il compilatore MIDL crea e inizializza automaticamente un EPV di gestione predefinito presupponendo che esista una routine di gestione con lo stesso nome per ogni routine nell'interfaccia e sia specificata nel file IDL.

Quando un server offre più implementazioni della stessa interfaccia, il server deve creare un EPV di gestione aggiuntivo per ogni implementazione. Ogni EPV deve contenere esattamente un punto di ingresso (indirizzo di una funzione) per ogni routine definita nel file IDL. L'applicazione server dichiara e inizializza una variabile EPV di gestione di tipo if-name**_SERVER_EPV** per ogni implementazione aggiuntiva dell'interfaccia. Per registrare gli EPV chiama RpcServerRegisterIf, RpcServerRegisterIfEx o RpcServerRegisterIf2 una volta per ogni tipo di oggetto supportato.

Quando il client effettua una chiamata di routine remota al server, l'EPV contenente il puntatore a funzione viene selezionato in base all'UUID dell'interfaccia e al tipo di oggetto. Il tipo di oggetto è derivato dall'UUID dell'oggetto dalla funzione di richiesta di oggetti o dal mapping basato su tabella controllato da RpcObjectSetType.

EPV manager

Per impostazione predefinita, il compilatore MIDL usa i nomi di routine del file IDL di un'interfaccia per generare un gestore EPV, che il compilatore inserisce direttamente nello stub del server. Questo EPV predefinito viene inizializzato in modo statico usando i nomi di routine dichiarati nella definizione dell'interfaccia.

Per registrare un gestore usando l'EPV predefinito, specificare NULL come valore del parametro MgrEpv in una chiamata alla funzione RpcServerRegisterIf, RpcServerRegisterIfEx o RpcServerRegisterIf2 . Se i nomi di routine usati da un gestore corrispondono a quelli della definizione dell'interfaccia, è possibile registrare questo gestore usando l'EPV predefinito dell'interfaccia generata dal compilatore MIDL. È anche possibile registrare un manager usando un EPV fornito dall'applicazione server.

Un server può (e talvolta deve) creare e registrare un EPV di gestione non Null per un'interfaccia. Per selezionare un'applicazione server fornita da EPV, passare l'indirizzo di un EPV il cui valore è stato dichiarato dal server come valore del parametro MgrEpv . Un valore non Null per il parametro MgrEpv esegue sempre l'override di un EPV predefinito nello stub del server.

Il compilatore MIDL genera automaticamente un tipo di dati EPV di gestione (RPC_MGR_EPV) per un'applicazione server da usare nella costruzione di EPV di gestione. Un gestore EPV deve contenere esattamente un punto di ingresso (indirizzo della funzione) per ogni routine definita nel file IDL.

Un server deve fornire un EPV non Null nei casi seguenti:

  • Quando i nomi delle routine manager differiscono dai nomi di routine dichiarati nella definizione dell'interfaccia
  • Quando il server usa l'EPV predefinito per la registrazione di un'altra implementazione dell'interfaccia

Un server dichiara un gestore EPV inizializzando una variabile di tipo if-name**_SERVER_EPV** per ogni implementazione dell'interfaccia.

Registrazione di una singola implementazione di un'interfaccia

Quando un server offre una sola implementazione di un'interfaccia, il server chiama RpcServerRegisterIf, RpcServerRegisterIfEx o RpcServerRegisterIf2 una sola volta. Nel caso standard, il server usa il gestore EPV predefinito. L'eccezione è quando il gestore usa nomi di routine diversi da quelli dichiarati nell'interfaccia.

Nel caso standard, si specificano i valori seguenti per le chiamate a RpcServerRegisterIf, RpcServerRegisterIfEx o RpcServerRegisterIf2:

  • EPV manager

    Per usare l'EPV predefinito, specificare un valore Null per il parametro MgrEpv .

  • Tipo di gestore UUID

    Quando si usa l'EPV predefinito, registrare l'interfaccia con un UUID di tipo gestore nil specificando un valore Null o un UUID nil per MgrTypeUuid un parametro. In questo caso, tutte le chiamate di routine remota, indipendentemente dall'UUID dell'oggetto nel relativo handle di associazione, vengono inviate all'EPV predefinito, presupponendo che non siano state effettuate chiamate RpcObjectSetType .

    È anche possibile specificare un tipo di gestore non nil UUID. In questo caso, è necessario chiamare anche la routine RpcObjectSetType .

Registrazione di più implementazioni di un'interfaccia

È possibile specificare più di un'implementazione delle procedure remote specificate nel file IDL. L'applicazione server chiama RpcObjectSetType per eseguire il mapping degli UUID dell'oggetto al tipo UUID e chiama RpcServerRegisterIf, RpcServerRegisterIfEx o RpcServerRegisterIf2 per associare EPV di gestione a un tipo UUID. Quando arriva una chiamata di procedura remota con il relativo UUID oggetto, la libreria di runtime del server RPC esegue il mapping dell'UUID dell'oggetto a un tipo UUID. L'applicazione server usa quindi il tipo UUID e l'UUID dell'interfaccia per selezionare il gestore EPV.

È anche possibile specificare la propria funzione per risolvere il mapping dall'UUID dell'oggetto al tipo di gestore UUID. La funzione di mapping viene specificata quando si chiama RpcObjectSetInqFn.

Per offrire più implementazioni di un'interfaccia, un server deve registrare ogni implementazione chiamando RpcServerRegisterIf, RpcServerRegisterIfEx o RpcServerRegisterIf2 separatamente. Per ogni implementazione registrata da un server, fornisce lo stesso parametro IfSpec , ma una coppia diversa di parametri MgrTypeUuid e MgrEpv .

Nel caso di più gestori, usare RpcServerRegisterIf, RpcServerRegisterIfEx o RpcServerRegisterIf2 come indicato di seguito:

  • EPV manager

    Per offrire più implementazioni di un'interfaccia, un server deve:

    Si noti che il server può anche registrarsi con il gestore EPV predefinito.

  • Tipo di gestore UUID

    Specificare un UUID di tipo di gestione per ogni EPV dell'interfaccia. È possibile specificare il tipo UUID (o valore Null ) per MgrTypeUuid per uno degli EPV di gestione. Ogni UUID di tipo deve essere diverso.

Regole per richiamare routine di Gestione

La libreria di runtime RPC invia una chiamata di procedura remota in ingresso a un gestore che offre l'interfaccia RPC richiesta. Quando più gestori vengono registrati per un'interfaccia, la libreria di runtime RPC deve selezionare una di esse. Per selezionare un gestore, la libreria di runtime RPC usa l'UUID dell'oggetto specificato dall'handle di associazione della chiamata.

La libreria di runtime applica le regole seguenti quando si interpreta l'UUID dell'oggetto di una chiamata di procedura remota:

  • UUID dell'oggetto Nil

    All'UUID di un oggetto nil viene assegnato automaticamente l'UUID di tipo nil(non è possibile specificare un UUID di oggetto nil nella routine RpcObjectSetType ). Pertanto, una chiamata di procedura remota il cui handle di associazione contiene un UUID dell'oggetto nil viene inviato automaticamente al gestore registrato con il tipo UUID nil, se presente.

  • UUID oggetto non null

    In linea di principio, una chiamata di procedura remota il cui handle di associazione contiene un UUID oggetto non nil deve essere elaborato da un gestore il cui tipo UUID corrisponde al tipo dell'UUID dell'oggetto. L'identificazione del gestore corretto richiede tuttavia che il server abbia specificato il tipo di UUID dell'oggetto chiamando la routine RpcObjectSetType .

    Se un server non riesce a chiamare la routine RpcObjectSetType per un UUID oggetto non nil, una chiamata di routine remota per tale oggetto UUID passa al gestore EPV che esegue chiamate di routine remota con un UUID oggetto nil, ovvero il tipo UUID nullo.

    Le chiamate di routine remota con un UUID oggetto non nil nell'handle di associazione non possono essere eseguite se al server assegnato tale oggetto non nil UUID un tipo UUID chiamando la routine RpcObjectSetType , ma non ha registrato anche un EPV di gestione per tale tipo UUID chiamando RpcServerRegisterIf, RpcServerRegisterIfEx o RpcServerRegisterIf2.

Nella tabella seguente vengono riepilogate le azioni usate dalla libreria di runtime per selezionare la routine di gestione.

UUID oggetto della chiamata Tipo di set di server per l'UUID dell'oggetto? Tipo EPV registrato nel server? Azione di invio
Nil Non applicabile Usa il gestore con l'UUID di tipo nil.
Nil Non applicabile No Errore (RPC_S_UNSUPPORTED_TYPE); rifiuta la chiamata alla procedura remota.
Non-nil Usa il gestore con lo stesso tipo UUID.
Non-nil No Ignorato Usa il gestore con l'UUID di tipo nil. Se nessun gestore con il tipo UUID nil, errore (RPC_S_UNSUPPORTEDTYPE); rifiuta la chiamata alla procedura remota.
Non-nil No Errore (RPC_S_UNSUPPORTEDTYPE); rifiuta la chiamata alla procedura remota.

 

L'UUID dell'oggetto della chiamata è l'UUID dell'oggetto trovato in un handle di associazione per una chiamata di routine remota.

Il server imposta il tipo dell'UUID dell'oggetto chiamando RpcObjectSetType per specificare il tipo UUID per un oggetto.

Il server registra il tipo per il gestore EPV chiamando RpcServerRegisterIf, RpcServerRegisterIfEx o RpcServerRegisterIf2 usando lo stesso tipo UUID.

Nota

All'UUID dell'oggetto nil viene sempre assegnato automaticamente l'UUID di tipo nil. Non è possibile specificare un UUID di un oggetto nil nella routine RpcObjectSetType .

 

Invio di una chiamata di procedura remota a una routine server-manager

Le tabelle seguenti illustrano i passaggi eseguiti dalla libreria di runtime RPC per inviare una chiamata di procedura remota a una routine server-manager.

Un caso semplice in cui il server registra l'EPV di gestione predefinito, è descritto nelle tabelle seguenti.

Tabella del Registro di sistema dell'interfaccia

UUID dell'interfaccia Tipo di gestore UUID Vettore del punto di ingresso
uuid1 Nil EPV predefinito

 

Tabella del Registro oggetti

UUID oggetto Tipo oggetto
Nil Nil
(Qualsiasi altro UUID oggetto) Nil

 

Mapping dell'handle di associazione a un vettore del punto di ingresso (EPV)

UUID dell'interfaccia (dall'handle di associazione client) UUID dell'oggetto (dall'handle di associazione client) Tipo di oggetto (dalla tabella del Registro di sistema oggetti) EPV manager (dalla tabella del Registro di sistema dell'interfaccia)
uuid1 Nil Nil EPV predefinito
Vedere sopra. uuidA Nil EPV predefinito

 

I passaggi seguenti descrivono le azioni eseguite dalla libreria di runtime del server RPC, come illustrato nelle tabelle precedenti, quando un client con interfaccia UUID uuid1 lo chiama.

  1. Il server chiama RpcServerRegisterIf, RpcServerRegisterIfEx o RpcServerRegisterIf2 per associare un'interfaccia offerta al tipo di gestore nil UUID e al gestore predefinito generato da MIDL EPV. Questa chiamata aggiunge una voce nella tabella del Registro di sistema dell'interfaccia. L'UUID dell'interfaccia è contenuto nel parametro IfSpec .

  2. Per impostazione predefinita, la tabella del Registro di sistema oggetti associa tutti gli UUID oggetto al tipo UUID di tipo nil. In questo esempio il server non chiama RpcObjectSetType.

  3. La libreria di runtime del server riceve un codice di procedura remota contenente l'UUID dell'interfaccia a cui appartiene la chiamata e l'UUID dell'oggetto dall'handle di associazione della chiamata.

    Per informazioni su come impostare un UUID oggetto in un handle di associazione, vedere le voci di riferimento di funzione seguenti:

  4. Usando l'UUID dell'interfaccia dalla chiamata alla procedura remota, la libreria di runtime del server individua tale UUID dell'interfaccia nella tabella del Registro di sistema dell'interfaccia.

    Se il server non ha registrato l'interfaccia utilizzando RpcServerRegisterIf, RpcServerRegisterIfEx o RpcServerRegisterIf2, la chiamata di procedura remota torna al chiamante con un codice di stato RPC_S_UNKNOWN_IF.

  5. Usando l'UUID dell'oggetto dall'handle di associazione, la libreria di runtime del server individua tale UUID oggetto nella tabella del Registro di sistema degli oggetti. In questo esempio tutti gli UUID oggetto eseguono il mapping al tipo di oggetto nil.

  6. La libreria di runtime del server individua il tipo di gestore nil nella tabella del Registro di sistema dell'interfaccia.

  7. La combinazione dell'UUID dell'interfaccia e del tipo nil nella tabella del Registro di sistema dell'interfaccia viene risolta nell'EPV predefinito, che contiene le routine di server-manager da eseguire per l'UUID dell'interfaccia presente nella chiamata alla procedura remota.

Si supponga che il server offra più interfacce e più implementazioni di ogni interfaccia, come descritto nelle tabelle seguenti.

Tabella del Registro di sistema dell'interfaccia

UUID dell'interfaccia UUID di tipo manager Vettore del punto di ingresso
uuid1 Nil epv1
uuid1 uuid3 epv4
uuid2 uuid4 epv2
uuid2 uuid7 epv3

 

Tabella del Registro di sistema oggetti

UUID oggetto Tipo oggetto
uuidA uuid3
uuidB uuid7
uuidC uuid7
uuidD uuid3
uuidE uuid3
uuidF uuid8
Nil Nil
(Qualsiasi altro UUID) Nil

 

Mapping dell'handle di associazione a un vettore di punti di ingresso

Interfaccia UUID (dall'handle di associazione client) Object UUID (dall'handle di associazione client) Tipo di oggetto (dalla tabella del Registro di sistema oggetti) Gestione EPV (dalla tabella del Registro di sistema di interfaccia)
uuid1 Nil Nil epv1
uuid1 uuidA uuid3 epv4
uuid1 uuidD uuid3 epv4
uuid1 uuidE uuid3 epv4
uuid2 uuidB uuid7 epv3
uuid2 uuidC uuid7 epv3

 

I passaggi seguenti descrivono le azioni eseguite dalla libreria run-time del server, come illustrato nelle tabelle precedenti quando un client con interfaccia UUID uuid2 e l'oggetto UUID uuidC lo chiama.

  1. Il server chiama RpcServerRegisterIf, RpcServerRegisterIfEx o RpcServerRegisterIf2 per associare le interfacce offerte con i diversi EPV di gestione. Le voci della tabella del Registro di sistema di interfaccia riflettono quattro chiamate di RpcServerRegisterIf, RpcServerRegisterIfEx o RpcServerRegisterIf2 per offrire due interfacce, con due implementazioni (EPV) per ogni interfaccia.

  2. Il server chiama RpcObjectSetType per stabilire il tipo di ogni oggetto che offre. Oltre all'associazione predefinita dell'oggetto nil a un tipo nil, tutti gli altri UUID oggetto non vengono trovati in modo esplicito nella tabella del Registro di sistema oggetti anche il mapping al tipo NIL UUID.

    In questo esempio il server chiama la routine RpcObjectSetType sei volte.

  3. La libreria runtime del server riceve una chiamata di routine remota contenente l'UUID dell'interfaccia a cui appartiene la chiamata e un UUID oggetto dall'handle di associazione della chiamata.

  4. Usando l'interfaccia UUID dalla chiamata alla procedura remota, la libreria run-time del server individua l'interfaccia UUID nella tabella del Registro di sistema dell'interfaccia.

  5. Usando l'UUID dell'oggetto UUID UUID dell'oggetto uuidC dall'handle di associazione, la libreria di runtime del server individua l'oggetto UUID nella tabella del Registro di sistema oggetti e rileva che esegue il mapping al tipo uuid7.

  6. Per individuare il tipo di gestione, la libreria di runtime del server combina l'interfaccia UUID, uuid2 e digitare uuid7 nella tabella del Registro di sistema dell'interfaccia. Questo problema viene risolto in epv3, che contiene la routine di gestione server da eseguire per la chiamata alla procedura remota.

Le routine in epv2 non verranno mai eseguite perché il server non ha chiamato la routine RpcObjectSetType per aggiungere eventuali oggetti con un tipo UUID di uuid4 alla tabella del Registro oggetti.

Una chiamata di procedura remota con l'interfaccia UUID uuid2 e l'oggetto UUID uuidF restituisce al chiamante con un codice di stato RPC_S_UNKNOWN_MGR_TYPE perché il server non ha chiamato RpcServerRegisterIf, RpcServerRegisterIfEx o RpcServerRegisterIf2 per registrare l'interfaccia con un tipo di gestore di uuid8.

Valori restituiti

Questa funzione restituisce uno dei valori seguenti.

Valore Significato
RPC_S_OK Operazione riuscita
RPC_S_TYPE_ALREADY_REGISTERED Tipo UUID già registrato

 

Specificare la funzione di richiesta dell'oggetto personalizzata

Prendere in considerazione un server che gestisce migliaia di oggetti di molti tipi diversi. Ogni volta che il server è stato avviato, l'applicazione server deve chiamare la funzione RpcObjectSetType per ogni oggetto, anche se i client potrebbero fare riferimento solo a pochi di essi (o richiedere molto tempo per farvi riferimento). È probabile che queste migliaia di oggetti siano su disco, quindi il recupero dei tipi richiederebbe molto tempo. Inoltre, la tabella interna che esegue il mapping dell'oggetto UUID al tipo di gestione UUID duplica essenzialmente il mapping gestito con gli oggetti stessi.

Per praticità, il set di funzioni RPC include la funzione RpcObjectSetInqFn. Con questa funzione è possibile fornire la funzione di richiesta dell'oggetto.

Ad esempio, è possibile fornire una funzione di richiesta oggetto personalizzata quando si esegue il mapping degli oggetti 100-199 al numero 1, 200-299 per digitare il numero 2 e così via. La funzione di indagine dell'oggetto può anche essere estesa a un file system distribuito, in cui l'applicazione server non dispone di un elenco di tutti i file (UUID oggetto) disponibili o quando i file dei nomi UUID oggetto nel file system e non si desidera preload di tutti i mapping tra uUID oggetto e UUID di tipo.

RpcBindingFromStringBinding

RpcBindingSetObject

RpcNsBindingExport

RpcNsBindingImportBegin

RpcNsBindingLookupBegin

RpcObjectSetType

RpcServerRegisterIf

RpcServerRegisterIf2

RpcServerRegisterIfEx

RpcServerUnregisterIf

RpcServerUnregisterIfEx