Share via


인터페이스 등록

이 섹션에서는 RPC 인터페이스를 등록하는 프로세스에 대한 자세한 설명을 제공합니다.

이 섹션의 정보는 다음 topics 제공됩니다.

인터페이스 등록 함수

서버는 RpcServerRegisterIf 함수를 호출하여 인터페이스를 등록합니다. 복잡한 서버 프로그램은 종종 둘 이상의 인터페이스를 지원합니다. 서버 애플리케이션은 지원하는 각 인터페이스에 대해 이 함수를 한 번 호출해야 합니다.

또한 서버는 각각 인터페이스의 함수를 자체적으로 구현하는 동일한 인터페이스의 여러 버전을 지원할 수 있습니다. 서버 프로그램에서 이 작업을 수행하는 경우 진입점 집합을 제공해야 합니다. 진입점은 인터페이스 버전에 대한 호출을 디스패치하는 관리자 루틴입니다. 인터페이스의 각 버전에 대해 하나의 진입점이 있어야 합니다. 진입점 그룹을 진입점 벡터라고 합니다. 자세한 내용은 진입점 벡터를 참조하세요.

RPC는 표준 함수 RpcServerRegisterIf 외에도 다른 인터페이스 등록 함수도 지원합니다. RpcServerRegisterIf2 함수는 등록 플래그 집합(인터페이스 등록 플래그 참조), 서버에서 수락할 수 있는 동시 원격 프로시저 호출 요청의 최대 수 및 들어오는 데이터 블록의 최대 크기(바이트)를 지정할 수 있도록 하여 RpcServerRegisterIf의 기능을 확장합니다.

RPC 라이브러리에는 RpcServerRegisterIfEx라는 함수도 포함되어 있습니다. RpcServerRegisterIf 함수와 마찬가지로 이 함수는 인터페이스를 등록합니다. 또한 서버 프로그램은 이 함수를 사용하여 등록 플래그 집합( 인터페이스 등록 플래그 참조), 서버가 수락할 수 있는 동시 원격 프로시저 호출 요청의 최대 수 및 보안 콜백 함수를 지정할 수 있습니다.

RpcServerRegisterIf, RpcServerRegisterIfExRpcServerRegisterIf2 함수는 내부 인터페이스 레지스트리 테이블의 값을 설정합니다. 이 테이블은 인터페이스 UUID 및 개체 UUID를 관리자 EPV에 매핑하는 데 사용됩니다. 관리자 EPV는 IDL 파일에 지정된 인터페이스의 각 함수 프로토타입에 대해 정확히 하나의 함수 포인터를 포함하는 함수 포인터의 배열입니다.

인터페이스의 여러 구현을 제공하기 위해 여러 EPV를 제공하는 방법에 대한 자세한 내용은 다중 인터페이스 구현을 참조하세요.

런타임 라이브러리는 인터페이스 레지스트리 테이블(RpcServerRegisterIf, RpcServerRegisterIfEx 또는 RpcServerRegisterIf2 호출에 의해 설정됨) 및 개체 레지스트리 테이블(함수 RpcObjectSetType에 대한 호출로 설정)을 사용하여 인터페이스 및 개체 UUID를 함수 포인터에 매핑합니다.

서버 프로그램이 RPC 런타임 라이브러리 레지스트리에서 인터페이스를 제거하도록 하려면 RpcServerUnregisterIf 함수를 호출합니다. 레지스트리에서 인터페이스가 제거되면 RPC 런타임 라이브러리는 더 이상 해당 인터페이스에 대한 새 호출을 수락하지 않습니다.

진입점 벡터

EPV(관리자 진입점 벡터)는 IDL 파일에 지정된 함수의 구현을 가리키는 함수 포인터의 배열입니다. 배열의 요소 수는 IDL 파일에 지정된 함수 수에 해당합니다. RPC는 인터페이스에 지정된 함수의 여러 구현을 나타내는 여러 진입점 벡터를 지원합니다.

MIDL 컴파일러는 관리자 EPV 생성에 사용할 관리자 EPV 데이터 형식을 자동으로 생성합니다. 데이터 형식의 이름은 if-name**_SERVER_EPV**입니다. 여기서 if-name 은 IDL 파일에서 인터페이스 식별자를 지정합니다.

MIDL 컴파일러는 인터페이스의 각 프로시저에 대해 동일한 이름의 관리자 루틴이 존재하고 IDL 파일에 지정된다는 가정 하에 기본 관리자 EPV를 자동으로 만들고 초기화합니다.

서버가 동일한 인터페이스의 여러 구현을 제공하는 경우 서버는 각 구현에 대해 하나의 추가 관리자 EPV를 만들어야 합니다. 각 EPV는 IDL 파일에 정의된 각 프로시저에 대해 정확히 하나의 진입점(함수 주소)을 포함해야 합니다. 서버 애플리케이션은 인터페이스의 각 추가 구현에 대해 if-name**_SERVER_EPV** 형식의 하나의 관리자 EPV 변수를 선언하고 초기화합니다. EPV를 등록하려면 RpcServerRegisterIf, RpcServerRegisterIfEx 또는 RpcServerRegisterIf2 를 지원하는 각 개체 형식에 대해 한 번씩 호출합니다.

클라이언트가 서버에 대한 원격 프로시저 호출을 하면 인터페이스 UUID 및 개체 형식에 따라 함수 포인터가 포함된 EPV가 선택됩니다. 개체 형식은 개체 조회 함수 또는 RpcObjectSetType에서 제어하는 테이블 기반 매핑에 의해 개체 UUID에서 파생됩니다.

관리자 EPV

기본적으로 MIDL 컴파일러는 인터페이스의 IDL 파일의 프로시저 이름을 사용하여 컴파일러가 서버 스텁에 직접 배치하는 관리자 EPV를 생성합니다. 이 기본 EPV는 인터페이스 정의에 선언된 프로시저 이름을 사용하여 정적으로 초기화됩니다.

기본 EPV를 사용하여 관리자를 등록하려면 RpcServerRegisterIf, RpcServerRegisterIfEx 또는 RpcServerRegisterIf2 함수에 대한 호출에서 MgrEpv 매개 변수 값으로 NULL을 지정합니다. 관리자가 사용하는 루틴 이름이 인터페이스 정의에 해당하는 경우 MIDL 컴파일러에서 생성된 인터페이스의 기본 EPV를 사용하여 이 관리자를 등록할 수 있습니다. 서버 애플리케이션에서 제공하는 EPV를 사용하여 관리자를 등록할 수도 있습니다.

서버는 인터페이스에 대해 null 이 아닌 관리자 EPV를 만들고 등록해야 하는 경우도 있습니다. 서버 애플리케이션에서 제공하는 EPV를 선택하려면 서버에서 값이 MgrEpv 의 값으로 선언된 EPV의 주소를 매개 변수로 전달합니다. MgrEpv 매개 변수에 대한 null이 아닌 값은 항상 서버 스텁의 기본 EPV를 재정의합니다.

MIDL 컴파일러는 서버 애플리케이션이 관리자 EPV를 생성하는 데 사용할 관리자 EPV 데이터 형식(RPC_MGR_EPV)을 자동으로 생성합니다. 관리자 EPV는 IDL 파일에 정의된 각 프로시저에 대해 정확히 하나의 진입점(함수 주소)을 포함해야 합니다.

서버는 다음 경우에 null 이 아닌 EPV를 제공해야 합니다.

  • 관리자 루틴의 이름이 인터페이스 정의에 선언된 프로시저 이름과 다른 경우
  • 서버가 인터페이스의 다른 구현을 등록하기 위해 기본 EPV를 사용하는 경우

서버는 인터페이스의 각 구현에 대해 if-name**_SERVER_EPV** 형식의 변수를 초기화하여 관리자 EPV를 선언합니다.

인터페이스의 단일 구현 등록

서버가 하나의 인터페이스 구현만 제공하는 경우 서버는 RpcServerRegisterIf, RpcServerRegisterIfEx 또는 RpcServerRegisterIf2를 한 번만 호출합니다. 표준 경우 서버는 기본 관리자 EPV를 사용합니다. (예외는 관리자가 인터페이스에 선언된 것과 다른 루틴 이름을 사용하는 경우입니다.)

표준 사례의 경우 RpcServerRegisterIf, RpcServerRegisterIfEx 또는 RpcServerRegisterIf2 호출에 대해 다음 값을 제공합니다.

  • 관리자 EPV

    기본 EPV를 사용하려면 MgrEpv 매개 변수에 null 값을 지정합니다.

  • 관리자 유형 UUID

    기본 EPV를 사용하는 경우 매개 변수 MgrTypeUuid대해 null 값 또는 nil UUID를 제공하여 Nil 관리자 형식 UUID에 인터페이스를 등록합니다. 이 경우 바인딩 핸들의 개체 UUID에 관계없이 모든 원격 프로시저 호출은 RpcObjectSetType 호출이 수행되지 않았다고 가정하여 기본 EPV로 디스패치됩니다.

    Nil이 아닌 관리자 유형 UUID를 제공할 수도 있습니다. 이 경우 RpcObjectSetType 루틴도 호출해야 합니다.

인터페이스의 여러 구현 등록

IDL 파일에 지정된 원격 프로시저의 구현을 둘 이상 제공할 수 있습니다. 서버 애플리케이션은 RpcObjectSetType 을 호출하여 UUID를 입력하는 개체 UUID를 매핑하고 RpcServerRegisterIf, RpcServerRegisterIfEx 또는 RpcServerRegisterIf2 를 호출하여 관리자 EPV를 UUID 형식과 연결합니다. 원격 프로시저 호출이 해당 개체 UUID와 함께 도착하면 RPC 서버 런타임 라이브러리는 개체 UUID를 UUID 형식에 매핑합니다. 그런 다음 서버 애플리케이션은 UUID 형식과 인터페이스 UUID를 사용하여 관리자 EPV를 선택합니다.

사용자 고유의 함수를 지정하여 개체 UUID에서 관리자 유형 UUID로 매핑을 resolve 수도 있습니다. RpcObjectSetInqFn을 호출할 때 매핑 함수를 지정합니다.

인터페이스의 여러 구현을 제공하려면 서버가 RpcServerRegisterIf, RpcServerRegisterIfEx 또는 RpcServerRegisterIf2를 별도로 호출하여 각 구현을 등록해야 합니다. 서버가 등록하는 각 구현에 대해 동일한 IfSpec 매개 변수를 제공하지만 다른 한 쌍의 MgrTypeUuidMgrEpv 매개 변수를 제공합니다.

여러 관리자의 경우 다음과 같이 RpcServerRegisterIf, RpcServerRegisterIfEx 또는 RpcServerRegisterIf2 를 사용합니다.

  • 관리자 EPV

    인터페이스의 여러 구현을 제공하려면 서버에서 다음을 수행해야 합니다.

    서버는 기본 관리자 EPV에 등록할 수도 있습니다.

  • 관리자 유형 UUID

    인터페이스의 각 EPV에 대한 관리자 유형 UUID를 제공합니다. 관리자 EPV 중 하나에 대해 매개 변수를 MgrTypeUuid에 대한 Nil 형식 UUID(또는 null 값)로 지정할 수 있습니다. 각 형식 UUID는 서로 달라야 합니다.

관리자 루틴 호출 규칙

RPC 런타임 라이브러리는 요청된 RPC 인터페이스를 제공하는 관리자에게 들어오는 원격 프로시저 호출을 디스패치합니다. 여러 관리자가 인터페이스에 등록되면 RPC 런타임 라이브러리가 그 중 하나를 선택해야 합니다. 관리자를 선택하기 위해 RPC 런타임 라이브러리는 호출의 바인딩 핸들에 지정된 개체 UUID를 사용합니다.

런타임 라이브러리는 원격 프로시저 호출의 개체 UUID를 해석할 때 다음 규칙을 적용합니다.

  • Nil 개체 UUID

    Nil 개체 UUID에는 Nil 형식 UUID가 자동으로 할당됩니다( RpcObjectSetType 루틴에서 nil 개체 UUID를 지정하는 것은 불법임). 따라서 바인딩 핸들에 nil 개체 UUID가 포함된 원격 프로시저 호출은 nil 형식 UUID(있는 경우)에 등록된 관리자로 자동으로 디스패치됩니다.

  • Nil이 아닌 개체 UUID

    기본적으로 바인딩 핸들에 Nil이 아닌 개체 UUID가 포함된 원격 프로시저 호출은 UUID 형식이 개체 UUID의 형식과 일치하는 관리자에 의해 처리되어야 합니다. 그러나 올바른 관리자를 식별하려면 서버가 RpcObjectSetType 루틴을 호출하여 해당 개체 UUID의 형식을 지정해야 합니다.

    서버가 Nil이 아닌 개체 UUID에 대해 RpcObjectSetType 루틴을 호출하지 못하면 해당 개체 UUID에 대한 원격 프로시저 호출은 Nil 개체 UUID(즉, nil 형식 UUID)를 사용하여 원격 프로시저 호출을 처리하는 관리자 EPV로 이동합니다.

    RpcObjectSetType 루틴을 호출하여 Nil이 아닌 개체 UUID 형식을 UUID 형식으로 할당한 서버가 RpcServerRegisterIf, RpcServerRegisterIfEx 또는 RpcServerRegisterIf2를 호출하여 UUID 형식에 대한 관리자 EPV를 등록하지 않은 경우 바인딩 핸들에서 Nil이 아닌 개체 UUID를 사용하는 원격 프로시저 호출을 실행할 수 없습니다.

다음 표에는 런타임 라이브러리가 관리자 루틴을 선택하는 데 사용하는 작업이 요약되어 있습니다.

호출의 개체 UUID 개체 UUID에 대한 서버 집합 형식 서버 등록 EPV 유형 디스패치 작업
없음 해당 없음 Nil 형식 UUID로 관리자를 사용합니다.
없음 적용할 수 없음 아니요 오류(RPC_S_UNSUPPORTED_TYPE); 는 원격 프로시저 호출을 거부합니다.
Nil이 아닌 경우 Yes Yes UUID 형식이 동일한 관리자를 사용합니다.
Nil이 아닌 경우 아니요 무시됨 Nil 형식 UUID로 관리자를 사용합니다. Nil 형식 UUID를 가진 관리자가 없으면 오류(RPC_S_UNSUPPORTEDTYPE); 는 원격 프로시저 호출을 거부합니다.
Nil이 아닌 경우 Yes 아니요 오류(RPC_S_UNSUPPORTEDTYPE); 는 원격 프로시저 호출을 거부합니다.

 

호출의 개체 UUID는 원격 프로시저 호출에 대한 바인딩 핸들에 있는 개체 UUID입니다.

서버는 RpcObjectSetType 을 호출하여 개체의 UUID 형식을 지정하여 개체 UUID의 형식을 설정합니다.

서버는 동일한 형식 UUID를 사용하여 RpcServerRegisterIf, RpcServerRegisterIfEx 또는 RpcServerRegisterIf2 를 호출하여 관리자 EPV에 대한 형식을 등록합니다.

참고

nil 개체 UUID는 항상 nil 형식 UUID를 자동으로 할당합니다. RpcObjectSetType 루틴에서 nil 개체 UUID를 지정하는 것은 불법입니다.

 

서버 관리자 루틴에 원격 프로시저 호출 디스패치

다음 표에서는 RPC 런타임 라이브러리가 원격 프로시저 호출을 서버 관리자 루틴으로 디스패치하는 데 걸리는 단계를 보여 줍니다.

서버가 기본 관리자 EPV를 등록하는 간단한 사례는 다음 표에 설명되어 있습니다.

인터페이스 레지스트리 테이블

인터페이스 UUID 관리자 유형 UUID 진입점 벡터
uuid1 없음 기본 EPV

 

개체 레지스트리 테이블

개체 UUID 개체 유형
없음 없음
(다른 모든 개체 UUID) 없음

 

바인딩 핸들을 EPV(진입점 벡터)에 매핑

인터페이스 UUID(클라이언트 바인딩 핸들에서) 개체 UUID(클라이언트 바인딩 핸들에서) 개체 형식(개체 레지스트리 테이블에서) 관리자 EPV(인터페이스 레지스트리 테이블)
uuid1 없음 없음 기본 EPV
위와 동일 uuidA 없음 기본 EPV

 

다음 단계에서는 UUID uuid1 인터페이스가 있는 클라이언트가 호출할 때 이전 표와 같이 RPC 서버의 런타임 라이브러리가 수행하는 작업에 대해 설명합니다.

  1. 서버는 RpcServerRegisterIf, RpcServerRegisterIfEx 또는 RpcServerRegisterIf2 를 호출하여 제공하는 인터페이스를 Nil 관리자 유형 UUID 및 MIDL에서 생성된 기본 관리자 EPV와 연결합니다. 이 호출은 인터페이스 레지스트리 테이블에 항목을 추가합니다. 인터페이스 UUID는 IfSpec 매개 변수에 포함되어 있습니다.

  2. 기본적으로 개체 레지스트리 테이블은 모든 개체 UUID를 Nil 형식 UUID와 연결합니다. 이 예제에서 서버는 RpcObjectSetType을 호출하지 않습니다.

  3. 서버 런타임 라이브러리는 호출이 속한 인터페이스 UUID와 호출의 바인딩 핸들에서 개체 UUID를 포함하는 원격 프로시저 코드를 받습니다.

    개체 UUID가 바인딩 핸들로 설정되는 방법에 대한 자세한 내용은 다음 함수 참조 항목을 참조하세요.

  4. 원격 프로시저 호출의 인터페이스 UUID를 사용하여 서버의 런타임 라이브러리는 인터페이스 레지스트리 테이블에서 해당 인터페이스 UUID를 찾습니다.

    서버가 RpcServerRegisterIf, RpcServerRegisterIfEx 또는 RpcServerRegisterIf2를 사용하여 인터페이스를 등록하지 않은 경우 원격 프로시저 호출은 RPC_S_UNKNOWN_IF 상태 코드를 사용하여 호출자에게 반환됩니다.

  5. 바인딩 핸들에서 개체 UUID를 사용하여 서버의 런타임 라이브러리는 개체 레지스트리 테이블에서 해당 개체 UUID를 찾습니다. 이 예제에서 모든 개체 UUID는 nil 개체 형식에 매핑됩니다.

  6. 서버의 런타임 라이브러리는 인터페이스 레지스트리 테이블에서 nil manager 형식을 찾습니다.

  7. 인터페이스 레지스트리 테이블에서 인터페이스 UUID와 nil 형식을 결합하면 원격 프로시저 호출에 있는 인터페이스 UUID에 대해 실행할 서버 관리자 루틴이 포함된 기본 EPV로 확인됩니다.

다음 표에 설명된 대로 서버가 여러 인터페이스와 각 인터페이스의 여러 구현을 제공한다고 가정합니다.

인터페이스 레지스트리 테이블

인터페이스 UUID 관리자 유형 UUID 진입점 벡터
uuid1 없음 epv1
uuid1 uuid3 epv4
uuid2 uuid4 epv2
uuid2 uuid7 epv3

 

개체 레지스트리 테이블

개체 UUID 개체 유형
uuidA uuid3
uuidB uuid7
uuidC uuid7
uuidD uuid3
uuidE uuid3
uuidF uuid8
없음 없음
(다른 모든 UUID) 없음

 

바인딩 핸들을 진입점 벡터에 매핑

인터페이스 UUID(클라이언트 바인딩 핸들에서) 개체 UUID(클라이언트 바인딩 핸들에서) 개체 형식(개체 레지스트리 테이블에서) 관리자 EPV(인터페이스 레지스트리 테이블)
uuid1 없음 없음 epv1
uuid1 uuidA uuid3 epv4
uuid1 uuidD uuid3 epv4
uuid1 uuidE uuid3 epv4
uuid2 uuidB uuid7 epv3
uuid2 uuidC uuid7 epv3

 

다음 단계에서는 인터페이스 UUID uuid2 및 개체 UUID uuidC 가 있는 클라이언트가 호출할 때 이전 표와 같이 서버의 런타임 라이브러리가 수행하는 작업을 설명합니다.

  1. 서버는 RpcServerRegisterIf, RpcServerRegisterIfEx 또는 RpcServerRegisterIf2 를 호출하여 제공하는 인터페이스를 다른 관리자 EPV와 연결합니다. 인터페이스 레지스트리 테이블의 항목은 RpcServerRegisterIf, RpcServerRegisterIfEx 또는 RpcServerRegisterIf2의 네 가지 호출을 반영하여 각 인터페이스에 대해 두 개의 구현(EPV)이 있는 두 개의 인터페이스를 제공합니다.

  2. 서버는 RpcObjectSetType 을 호출하여 제공하는 각 개체의 형식을 설정합니다. nil 개체와 nil 형식의 기본 연결 외에도 개체 레지스트리 테이블에서 명시적으로 찾을 수 없는 다른 모든 개체 UUID도 Nil 형식 UUID에 매핑됩니다.

    이 예제에서 서버는 RpcObjectSetType 루틴을 6번 호출합니다.

  3. 서버 런타임 라이브러리는 호출이 속한 인터페이스 UUID와 호출의 바인딩 핸들에서 개체 UUID를 포함하는 원격 프로시저 호출을 받습니다.

  4. 원격 프로시저 호출의 인터페이스 UUID를 사용하여 서버의 런타임 라이브러리는 인터페이스 레지스트리 테이블에서 인터페이스 UUID를 찾습니다.

  5. 바인딩 핸들에서 uuidC 개체 UUID를 사용하여 서버의 런타임 라이브러리는 개체 레지스트리 테이블에서 개체 UUID를 찾고 uuid7 형식에 매핑되는 것을 찾습니다.

  6. 관리자 유형을 찾기 위해 서버의 런타임 라이브러리는 인터페이스 레지스트리 테이블의 인터페이스 UUID, uuid2uuid7 형식을 결합합니다. 이는 epv3으로 확인되며, 여기에는 원격 프로시저 호출에 대해 실행할 서버 관리자 루틴이 포함됩니다.

서버가 uuid4 형식의 개체를 개체 레지스트리 테이블에 추가하기 위해 RpcObjectSetType 루틴을 호출하지 않았기 때문에 epv2의 루틴은 실행되지 않습니다.

서버가 RpcServerRegisterIf, RpcServerRegisterIfEx 또는 RpcServerRegisterIf2를 호출하여 uuid8의 관리자 형식으로 인터페이스를 등록하지 않았기 때문에 인터페이스 UUID uuid2 및 개체 UUID uuidF를 사용하는 원격 프로시저 호출은 RPC_S_UNKNOWN_MGR_TYPE 상태 코드를 사용하여 호출자에게 반환됩니다.

반환 값

이 함수는 다음 값 중 하나를 반환합니다.

의미
RPC_S_OK Success
RPC_S_TYPE_ALREADY_REGISTERED 이미 등록된 UUID 유형

 

사용자 고유의 개체 조회 함수 제공

다양한 유형의 수천 개의 개체를 관리하는 서버를 고려합니다. 서버가 시작될 때마다 클라이언트가 일부만 참조하거나 참조하는 데 시간이 오래 걸릴 수 있더라도 서버 애플리케이션은 모든 개체에 대해 RpcObjectSetType 함수를 호출해야 합니다. 이러한 수천 가지 개체가 디스크에 있을 수 있으므로 형식을 검색하는 데 시간이 오래 걸립니다. 또한 UUID 개체를 관리자 유형 UUID에 매핑하는 내부 테이블은 기본적으로 개체 자체와 유지 관리되는 매핑을 복제합니다.

편의를 위해 RPC 함수 집합에는 RpcObjectSetInqFn 함수가 포함됩니다. 이 함수를 사용하면 고유한 개체 조회 함수를 제공합니다.

예를 들어 개체 100~199를 숫자 1, 200~299 형식으로 매핑하여 숫자 2 등을 입력할 때 고유한 개체 조회 함수를 제공할 수 있습니다. 개체 조회 함수는 서버 애플리케이션에 사용 가능한 모든 파일(개체 UUID) 목록이 없거나 파일 시스템의 개체 UUID 이름 파일이 있고 개체 UUID와 형식 UUID 간의 모든 매핑을 미리 로드하지 않으려는 분산 파일 시스템으로 확장할 수도 있습니다.

RpcBindingFromStringBinding

RpcBindingSetObject

RpcNsBindingExport

RpcNsBindingImportBegin

RpcNsBindingLookupBegin

RpcObjectSetType

RpcServerRegisterIf

RpcServerRegisterIf2

RpcServerRegisterIfEx

RpcServerUnregisterIf

RpcServerUnregisterIfEx