다음을 통해 공유


컨텍스트 핸들을 사용하여 서버 개발

서버 프로그램 개발의 관점에서 컨텍스트 핸들은 형식화되지 않은 포인터입니다. 서버 프로그램은 메모리의 데이터 또는 다른 형태의 스토리지(예: 디스크의 파일)를 가리켜 컨텍스트 핸들을 초기화합니다.

instance 경우 클라이언트가 컨텍스트 핸들을 사용하여 데이터베이스의 레코드에 대한 일련의 업데이트를 요청한다고 가정합니다. 클라이언트는 서버에서 원격 프로시저를 호출하고 검색 키를 전달합니다. 서버 프로그램은 데이터베이스에서 검색 키를 검색하고 일치하는 레코드의 정수 레코드 번호를 가져옵니다. 그런 다음 서버는 레코드 번호가 포함된 메모리 위치에서 포인터를 void로 가리킬 수 있습니다. 반환될 때 원격 프로시저는 반환 값 또는 매개 변수 목록을 통해 포인터를 컨텍스트 핸들로 반환해야 합니다. 클라이언트는 레코드를 업데이트하기 위해 원격 프로시저를 호출할 때마다 서버에 포인터를 전달해야 합니다. 이러한 각 업데이트 작업 중에 서버는 void 포인터를 정수에 대한 포인터로 캐스팅합니다.

서버 프로그램이 컨텍스트 데이터에서 컨텍스트 핸들을 가리키면 핸들이 열린 것으로 간주됩니다. NULL 값을 포함하는 핸들이 닫힙니다. 서버는 클라이언트가 원격 프로시저를 호출하여 닫을 때까지 열린 컨텍스트 핸들을 유지 관리합니다. 핸들이 열려 있는 동안 클라이언트 세션이 종료되면 RPC 런타임은 서버 런다운 루틴을 호출하여 핸들을 해제합니다.

다음 코드 조각은 서버가 컨텍스트 핸들을 구현하는 방법을 보여 줍니다. 이 예제에서 서버는 클라이언트가 원격 프로시저를 사용하여 쓰는 데이터 파일을 유지 관리합니다. 컨텍스트 정보는 서버가 데이터를 쓸 파일의 현재 위치를 추적하는 파일 핸들입니다. 파일 핸들은 원격 프로시저 호출에 대한 매개 변수 목록의 컨텍스트 핸들로 패키지됩니다. 구조체에는 파일 이름과 파일 핸들이 포함됩니다. 이 예제의 인터페이스 정의는 컨텍스트 핸들을 사용하여 인터페이스 개발에 표시됩니다.

/* cxhndlp.c (fragment of file containing remote procedures) */
typedef struct 
{
     FILE* hFile;
     char   achFile[256];
} FILE_CONTEXT_TYPE;

RemoteOpen 함수는 서버에서 파일을 엽니다.

short RemoteOpen(
    PPCONTEXT_HANDLE_TYPE pphContext,
    unsigned char *pszFileName)
{
    FILE               *hFile;
    FILE_CONTEXT_TYPE  *pFileContext;
 
    if ((hFile = fopen(pszFileName, "r")) == NULL) 
    {
        *pphContext = (PCONTEXT_HANDLE_TYPE) NULL;
        return(-1);
    }
    else 
    {
        pFileContext = (FILE_CONTEXT_TYPE *) 
                       MIDL_user_allocate(sizeof(FILE_CONTEXT_TYPE));
        pFileContext->hFile = hFile;
        // check if pszFileName is longer than 256 and if yes, return
        // an error
        strcpy_s(pFileContext->achFile, srlen(pszFileName), pszFileName);
        *pphContext = (PCONTEXT_HANDLE_TYPE) pFileContext;
        return(0);
    }
}

RemoteRead 함수는 서버에서 파일을 읽습니다.

short RemoteRead(
    PCONTEXT_HANDLE_TYPE phContext, 
    unsigned char *pbBuf, 
    short *pcbBuf) 
{ 
    FILE_CONTEXT_TYPE *pFileContext; 
    printf("in RemoteRead\n"); 
    pFileContext = (FILE_CONTEXT_TYPE *) phContext; 
    *pcbBuf = (short) fread(pbBuf, sizeof(char), 
                            BUFSIZE, 
                            pFileContext->hFile); 
    return(*pcbBuf); 
}

RemoteClose 함수는 서버의 파일을 닫습니다. 서버 애플리케이션은 close 함수의 일부로 컨텍스트 핸들에 NULL 을 할당해야 합니다. 이는 컨텍스트 핸들이 삭제된 서버 스텁 및 RPC 런타임 라이브러리와 통신합니다. 그렇지 않으면 연결이 열린 상태로 유지되고 결국 컨텍스트 런다운이 발생합니다.

void RemoteClose(PPCONTEXT_HANDLE_TYPE pphContext)
{
    FILE_CONTEXT_TYPE *pFileContext;
 
    if (*pphContext == NULL)
    {
        //Log error, client tried to close a NULL handle.
        return;
    }
    pFileContext = (FILE_CONTEXT_TYPE *)*pphContext;
    printf("File %s closed.\n", pFileContext->achFile);
    fclose(pFileConext->hFile);
    MIDL_user_free(pFileContext);
 
    // This tells the run-time, when it is marshalling the out 
    // parameters, that the context handle has been closed normally.
    *pphContext = NULL;
}

참고

클라이언트가 방향 특성이 있는 호출에 유효한 컨텍스트 핸들을 전달해야 하지만 RPC는 이 방향 특성 조합에 대해 NULL 컨텍스트 핸들을 거부하지 않습니다. NULL 컨텍스트 핸들은 NULL 포인터로 서버에 전달됩니다. NULL 포인터가 수신될 때 액세스 위반을 방지하기 위해 [in, out] 컨텍스트 핸들을 포함하는 호출에 대한 서버 코드를 작성해야 합니다.