클라이언트에서 입력 파이프 구현
입력 파이프를 사용하여 클라이언트에서 서버로 데이터를 전송하는 경우 끌어오기 프로시저를 구현해야 합니다. 끌어오기 프로시저는 전송할 데이터를 찾고, 데이터를 버퍼로 읽고, 보낼 요소 수를 설정해야 합니다. 서버가 데이터를 자체로 끌어오기 시작할 때 모든 데이터가 버퍼에 있어야 하는 것은 아닙니다. 끌어오기 프로시저는 버퍼를 증분 방식으로 채울 수 있습니다.
보낼 데이터가 더 이상 없으면 프로시저는 마지막 인수를 0으로 설정합니다. 모든 데이터가 전송되면 끌어오기 프로시저는 반환하기 전에 필요한 정리를 수행해야 합니다. [in, out] 파이프인 매개 변수의 경우 끌어오기 프로시저는 모든 데이터가 전송된 후 클라이언트의 상태 변수를 다시 설정해야 푸시 프로시저가 데이터를 수신하는 데 사용할 수 있습니다.
다음 예제는 SDK(플랫폼 소프트웨어 개발 키트)에 포함된 Pipedemo 프로그램에서 추출됩니다.
//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
이 예제에는 MIDL 컴파일러에서 생성된 헤더 파일이 포함됩니다. 자세한 내용은 IDL 파일에서 파이프 정의를 참조하세요. 또한 사용하는 변수를 globalPipeData라는 데이터 원본으로 선언합니다. globalBuffer 변수는 끌어오기 프로시저가 globalPipeData에서 가져온 데이터 블록을 보내는 데 사용하는 버퍼입니다.
SendLongs 함수는 입력 파이프를 선언하고 데이터 원본 변수 globalPipeData에 대한 메모리를 할당합니다. 클라이언트/서버 프로그램에서 데이터 원본은 클라이언트가 만드는 파일 또는 구조일 수 있습니다. 클라이언트 프로그램이 서버에서 데이터를 가져오고 처리한 다음 입력 파이프를 사용하여 서버로 반환하도록 할 수도 있습니다. 이 간단한 예제에서 데이터 원본은 긴 정수의 동적으로 할당된 버퍼입니다.
전송을 시작하기 전에 클라이언트는 상태 변수, 끌어오기 프로시저 및 할당 프로시저에 대한 포인터를 설정해야 합니다. 이러한 포인터는 클라이언트가 선언하는 파이프 변수에 유지됩니다. 이 경우 SendLongs는 inPipe를 선언합니다. 상태 변수에 적절한 데이터 형식을 사용할 수 있습니다.
클라이언트는 서버에서 원격 프로시저를 호출하여 파이프 간에 데이터 전송을 시작합니다. 원격 프로시저를 호출하면 클라이언트가 전송할 준비가 되었다는 것을 서버 프로그램에 알릴 수 있습니다. 그런 다음 서버는 데이터를 자체로 끌어올 수 있습니다. 이 예제에서는 InPipe라는 원격 프로시저를 호출합니다. 데이터가 서버로 전송되면 SendLongs 함수는 동적으로 할당된 버퍼를 해제합니다.
버퍼가 필요할 때마다 메모리를 할당하는 대신 이 예제의 할당 프로시저는 단순히 변수 globalBuffer에 대한 포인터를 설정합니다. 끌어오기 프로시저는 데이터를 전송할 때마다 이 버퍼를 다시 사용합니다. 더 복잡한 클라이언트 프로그램은 서버가 클라이언트에서 데이터를 가져올 때마다 새 버퍼를 할당해야 할 수 있습니다.
클라이언트 스텁은 끌어오기 프로시저를 호출합니다. 이 예제의 끌어오기 프로시저는 상태 변수를 사용하여 읽을 전역 데이터 원본 버퍼의 다음 위치를 추적합니다. 원본 버퍼에서 파이프 버퍼로 데이터를 읽습니다. 클라이언트 스텁은 데이터를 서버로 전송합니다. 모든 데이터가 전송되면 끌어오기 프로시저는 버퍼 크기를 0으로 설정합니다. 이렇게 하면 서버에서 데이터 끌어 오는 것을 중지하도록 지시합니다.
관련 항목