서버 쪽 비동기 파이프 처리
비동기 함수의 관리자 루틴은 항상 비동기 핸들을 첫 번째 매개 변수로 받습니다. 서버는 이 핸들을 사용하여 회신을 보내고 사용할 수 있게 되면 출력 파이프 데이터를 보냅니다. 핸들은 RpcAsyncCompleteCall 이 호출되거나, RpcAsyncAbortCall에서 호출이 중단되거나, 관리자 루틴에서 예외가 발생할 때까지 유효한 상태로 유지됩니다. 애플리케이션은 호출을 완료하기 전에 업데이트하기 위해 [out] 및 [in, out] 매개 변수에 대한 모든 최상위 포인터를 추적해야 합니다. 또한 애플리케이션은 [in] 및 [out] 파이프를 추적해야 합니다.
서버는 클라이언트와 동일한 방식으로 비동기 파이프 데이터를 보냅니다. 클라이언트 쪽 비동기 파이프 처리를 참조하세요.
서버는 클라이언트와 동일한 방식으로 비동기 파이프 데이터를 받습니다. 수신 메커니즘이 APC(비동기 프로시저 호출)인 경우 서버는 스레드 핸들(pAsync-u.APC.hThread>)을 지정하고 런타임 라이브러리에 비동기 핸들을 등록해야 합니다.
예제
이 예제에서 서버 관리자 루틴인 MyAsyncPipeFunc는 클라이언트의 원격 프로시저 호출을 처리합니다.
typedef struct
{
PRPC_ASYNC_STATE pAsync;
ASYNC_INTPIPE *inpipe;
ASYNC_INTPIPE *outpipe;
int i;
int *b;
int PipeBuffer[ASYNC_CHUNK_SIZE];
} PIPE_CALL_COOKIE;
void MyAsyncPipeFunc(
IN PRPC_ASYNC_STATE pAsync,
IN RPC_BINDING_HANDLE hBinding,
IN int a,
IN ASYNC_INTPIPE *inpipe,
OUT ASYNC_INTPIPE *outpipe,
OUT int *b)
{
unsigned long ThreadIdentifier;
HANDLE HandleToThread;
PIPE_CALL_COOKIE *PipeCallCookie;
PipeCallCookie = new PIPE_CALL_COOKIE;
PipeCallCookie->pAsync = pAsync;
PipeCallCookie->inpipe = inpipe;
PipeCallCookie->outpipe = outpipe;
PipeCallCookie->b = b;
pAsync->u.APC.hThread = 0;
pAsync->u.APC.hThread = CreateThread(
0, DefaultThreadStackSize,
(LPTHREAD_START_ROUTINE)
ThreadProcPipes,
PipeCallCookie, 0,
&ThreadIdentifier);
}// endMyAsyncPipeFunc
//Sending pipe data
//This APC routine is called when a pipe send completes,
//or when an asynchronous call completes.
//This thread routine receives pipe data, processes the call,
//sends the reply back to the client, and
//completes the asynchronous call.
void ThreadProcPipes(IN PIPE_CALL_COOKIE *Cookie)
{
int *ptr ;
int n ;
int retval ;
while (pAsync->u.APC.hThread == 0)
{
Sleep(10);
}
pAsync->Flags = RPC_C_NOTIFY_ON_SEND_COMPLETE;
pAsync->UserInfo = (void *) PipeCallCookie;
pAsync->NotificationType = RpcNotificationTypeApc;
pAsync->u.APC.NotificationRoutine = MyAsyncPipeAPCRoutine;
pAsync->u.APC.hThread = HandleToThread;
RpcAsyncRegisterHandle(pAsync);
while (!fDone)
{
Cookie->inpipe->pull(
Cookie->inpipe.state,
(int *) Cookie->PipeBuffer,
ASYNC_CHUNK_SIZE,
&num_elements);
switch (Status)
{
case RPC_S_ASYNC_CALL_PENDING:
if (SleepEx(INFINITE, TRUE) != WAIT_IO_COMPLETION)
{
RpcRaiseException(APP_ERROR) ;
}
break;
case RPC_S_OK:
if (num_elements == 0)
{
fDone = 1;
}
else
{
// process the received data
}
break;
default:
fDone = 1;
break;
}
}
Cookie->i = 1;
Cookie->outpipe->push(
Cookie->outpipe.state,
0,
Cookie->PipeBuffer,
ASYNC_CHUNK_SIZE) ;
while (Cookie->i < ASYNC_NUM_CHUNKS+1)
{
if (SleepEx(INFINITE, TRUE) != WAIT_IO_COMPLETION)
{
RpcRaiseException (APP_ERROR);
}
}
// sending non pipe reply
*(Cookie->b) = 10;
Status = RpcAsyncCompleteCall (Cookie->pAsync, &retval);
}
void MyAsyncPipeAPCRoutine (
IN PRPC_ASYNC_STATE pAsync,
IN void *Context,
IN unsigned int Flags)
{
PIPE_CALL_COOKIE *Cookie = (PIPE_CALL_COOKIE *) pAsync->UserInfo;
if (Flags & RPC_ASYNC_PIPE_SEND_COMPLETE)
{
if (Cookie->i & ASYNC_NUM_CHUNKS)
{
Cookie->outpipe->push(
Cookie->outpipe.state,
0,
(int *) Cookie->PipeBuffer,
ASYNC_CHUNK_SIZE);
Cookie->i++ ;
}
else
{
pAsync->Flags = 0;
Cookie->outpipe->push(Cookie->outpipe.state, 0, 0, 0);
Cookie->i++;
}
}
}
관련 항목