Implementace vstupních kanálů v klientovi
Při použití vstupního kanálu k přenosu dat z klienta na server musíte implementovat proceduru načítání dat. Postup stažení musí najít data, která se mají přenést, načíst data do vyrovnávací paměti a nastavit počet prvků k odeslání. Ne všechna data musí být ve vyrovnávací paměti, když server začne stahovat data do sebe. Procedura vyžádání změn může přírůstkově vyplnit vyrovnávací paměť.
Pokud neexistují žádná další data k odeslání, nastaví procedura poslední argument na nulu. Po odeslání všech dat by procedura vyžádání změn měla před vrácením provést potřebné vyčištění. U parametru, který je kanálem [in, out], musí procedura pro vytažení po přenosu všech dat obnovit stavovou proměnnou klienta, aby ji procedura push mohla použít k příjmu dat.
Následující příklad se extrahuje z programu Pipedemo, který je součástí sady SDK (Platform Software Development Kit).
//file: client.c (fragment)
#include <windows.h>
#include "pipedemo.h"
long *globalPipeData;
long globalBuffer[BUF_SIZE];
ulong pipeDataIndex; /* state variable */
void SendLongs()
{
LONG_PIPE inPipe;
int i;
globalPipeData =
(long *)malloc( sizeof(long) * PIPE_SIZE );
for (i=0; i<PIPE_SIZE; i++)
globalPipeData[i] = IN_VALUE;
pipeDataIndex = 0;
inPipe.state = (rpc_ss_pipe_state_t )&pipeDataIndex;
inPipe.pull = PipePull;
inPipe.alloc = PipeAlloc;
InPipe( inPipe ); /* Make the rpc */
free( (void *)globalPipeData );
}//end SendLongs
void PipeAlloc( rpc_ss_pipe_state_t stateInfo,
ulong requestedSize,
long **allocatedBuffer,
ulong *allocatedSize )
{
ulong *state = (ulong *)stateInfo;
if ( requestedSize > (BUF_SIZE*sizeof(long)) )
{
*allocatedSize = BUF_SIZE * sizeof(long);
}
else
{
*allocatedSize = requestedSize;
}
*allocatedBuffer = globalBuffer;
} //end PipeAlloc
void PipePull( rpc_ss_pipe_state_t stateInfo,
long *inputBuffer,
ulong maxBufSize,
ulong *sizeToSend )
{
ulong currentIndex;
ulong i;
ulong elementsToRead;
ulong *state = (ulong *)stateInfo;
currentIndex = *state;
if (*state >= PIPE_SIZE )
{
*sizeToSend = 0; /* end of pipe data */
*state = 0; /* Reset the state = global index */
}
else
{
if ( currentIndex + maxBufSize > PIPE_SIZE )
elementsToRead = PIPE_SIZE - currentIndex;
else
elementsToRead = maxBufSize;
for (i=0; i < elementsToRead; i++)
{
/*client sends data */
inputBuffer[i] = globalPipeData[i + currentIndex];
}
*state += elementsToRead;
*sizeToSend = elementsToRead;
}
}//end PipePull
Tento příklad obsahuje soubor hlaviček vygenerovaný kompilátorem MIDL. Podrobnosti najdete v tématu Definování kanálů v souborech IDL. Deklaruje také proměnnou, která se používá jako zdroj dat s názvem globalPipeData. Proměnná globalBuffer je vyrovnávací paměť, kterou procedura stahování používá pro odesílání bloků dat, které získává z globalPipeData.
Funkce SendLongs deklaruje vstupní kanál a přiděluje paměť pro proměnnou zdroje dat globalPipeData. V programu klienta nebo serveru může být zdrojem dat soubor nebo struktura, kterou klient vytvoří. Klientský program také může získávat data ze serveru, zpracovávat je a vracet ho na server pomocí vstupního kanálu. V tomto jednoduchém příkladu je zdrojem dat dynamicky přidělená vyrovnávací paměť dlouhých celých čísel.
Před zahájením přenosu musí klient nastavit ukazatele na proměnnou stavu, proceduru pull a proceduru alokace. Tyto ukazatele se uchovávají v proměnné potrubí, kterou klient deklaruje. V tomto případě SendLongs deklaruje inPipe. Pro proměnnou stavu můžete použít libovolný vhodný datový typ.
Klienti inicializuje přenos dat přes kanál vyvoláním vzdálené procedury na serveru. Volání vzdálené procedury informuje serverový program, že klient je připravený na přenos. Server pak může stáhnout data k sobě. Tento příklad vyvolá vzdálenou proceduru s názvem InPipe. Když jsou data přenesena na server, funkce SendLongs uvolní dynamicky přidělenou vyrovnávací paměť.
Namísto přidělení paměti pokaždé, když je potřeba vyrovnávací paměť, by se měla použít jiná metoda. Postup alokace v tomto příkladu jednoduše nastaví ukazatel na proměnnou globalBuffer. Postup pull tuto vyrovnávací paměť opět použije při každém přenosu dat. Složitější klientské programy mohou potřebovat přidělit novou vyrovnávací paměť pokaždé, když server načte data z klienta.
Stub klienta volá pull proceduru. Postup vyžádání v tomto příkladu používá proměnnou stavu ke sledování následující pozice v globální vyrovnávací paměti zdroje dat ke čtení. Čte data ze zdrojové vyrovnávací paměti do vyrovnávací paměti kanálu. Klientský stub přenáší data na server. Po odeslání všech dat nastaví procedura stažení velikost vyrovnávací paměti na nulu. To serveru říká, aby přestal stahovat data.
Související témata