클라이언트에서 출력 파이프 구현
출력 파이프를 사용하여 서버에서 클라이언트로 데이터를 전송하는 경우 클라이언트에서 푸시 프로시저를 구현해야 합니다. 푸시 프로시저는 클라이언트 스텁에서 버퍼 및 요소 수에 대한 포인터를 사용하고 요소 수가 0보다 크면 데이터를 처리합니다. 예를 들어 스텁의 버퍼에서 자체 메모리로 데이터를 복사할 수 있습니다. 또는 스텁의 버퍼에서 데이터를 처리하고 파일에 저장할 수 있습니다. 요소 수가 0과 같으면 푸시 프로시저는 반환하기 전에 필요한 정리 작업을 완료합니다.
다음 예제에서 클라이언트 함수 ReceiveLongs는 파이프 구조와 전역 메모리 버퍼를 할당합니다. 구조를 초기화하고 원격 프로시저를 호출한 다음 메모리를 해제합니다.
예제
//file: client.c (fragment)
#include <windows.h>
#include "pipedemo.h"
long * globalPipeData;
long globalBuffer[BUF_SIZE];
ulong pipeDataIndex; /* state variable */
void ReceiveLongs()
{
LONG_PIPE *outputPipe;
idl_long_int i;
globalPipeData =
(long *)malloc( sizeof(long) * PIPE_SIZE );
pipeDataIndex = 0;
outputPipe.state = (rpc_ss_pipe_state_t )&pipeDataIndex;
outputPipe.push = PipePush;
outputPipe.alloc = PipeAlloc;
OutPipe( &outputPipe ); /* Make the rpc */
free( (void *)globalPipeData );
}//end ReceiveLongs()
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 PipePush( rpc_ss_pipe_state_t stateInfo,
long *buffer,
ulong numberOfElements )
{
ulong elementsToCopy, i;
ulong *state = (ulong *)stateInfo;
if (numberOfElements == 0)/* end of data */
{
*state = 0; /* Reset the state = global index */
}
else
{
if (*state + numberOfElements > PIPE_SIZE)
elementsToCopy = PIPE_SIZE - *state;
else
elementsToCopy = numberOfElements;
for (i=0; i <elementsToCopy; i++)
{
/*client receives data */
globalPipeData[*state] = buffer[i];
(*state)++;
}
}
}//end PipePush
이 예제에는 MIDL 컴파일러에서 생성된 헤더 파일이 포함됩니다. 자세한 내용은 IDL 파일에서 파이프 정의를 참조하세요. 또한 데이터 싱크로 사용하는 globalPipeData 변수를 선언합니다. globalBuffer 변수는 푸시 프로시저가 globalPipeData에 저장하는 데이터 블록을 수신하는 데 사용하는 버퍼입니다.
ReceiveLongs 함수는 파이프를 선언하고 전역 데이터 싱크 변수에 대한 메모리 공간을 할당합니다. 클라이언트/서버 프로그램에서 데이터 싱크는 클라이언트가 만드는 파일 또는 데이터 구조일 수 있습니다. 이 간단한 예제에서 데이터 원본은 긴 정수의 동적으로 할당된 버퍼입니다.
데이터 전송을 시작하기 전에 클라이언트 프로그램에서 출력 파이프 구조를 초기화해야 합니다. 상태 변수, 푸시 프로시저 및 할당 프로시저에 대한 포인터를 설정해야 합니다. 이 예제에서는 출력 파이프 변수를 outputPipe라고 합니다.
클라이언트는 서버에서 원격 프로시저를 호출하여 데이터를 받을 준비가 되었음을 서버에 알릴 수 있습니다. 이 예제에서는 원격 프로시저를 OutPipe라고 합니다. 클라이언트가 원격 프로시저를 호출하면 서버가 데이터 전송을 시작합니다. 데이터가 도착할 때마다 클라이언트 스텁은 필요에 따라 클라이언트의 할당 및 푸시 프로시저를 호출합니다.
버퍼가 필요할 때마다 메모리를 할당하는 대신 이 예제의 할당 프로시저는 변수 globalBuffer에 대한 포인터를 설정합니다. 그런 다음 끌어오기 프로시저는 데이터를 전송할 때마다 이 버퍼를 다시 사용합니다. 더 복잡한 클라이언트 프로그램은 서버가 클라이언트에서 데이터를 가져올 때마다 새 버퍼를 할당해야 할 수 있습니다.
이 예제의 푸시 프로시저는 상태 변수를 사용하여 전역 데이터 싱크 버퍼에 데이터를 저장할 다음 위치를 추적합니다. 파이프 버퍼의 데이터를 싱크 버퍼에 씁니다. 그런 다음 클라이언트 스텁은 서버에서 다음 데이터 블록을 수신하고 파이프 버퍼에 저장합니다. 모든 데이터가 전송되면 서버는 크기가 0인 버퍼를 전송합니다. 이렇게 하면 푸시 프로시저가 데이터 수신을 중지합니다.
관련 항목