서버 호스트 시스템 찾기

서버 호스트 시스템은 분산 애플리케이션의 서버 프로그램을 실행하는 컴퓨터입니다. 네트워크에 하나 이상의 서버 호스트 시스템이 있을 수 있습니다. 클라이언트 프로그램에서 연결할 서버를 찾는 방법은 프로그램의 요구 사항에 따라 달라집니다.

서버 호스트 시스템을 찾는 방법에는 두 가지가 있습니다.

  • 클라이언트 소스 코드, 환경 변수 또는 애플리케이션별 구성 파일의 문자열에 저장된 정보를 사용합니다. 클라이언트 애플리케이션은 문자열의 데이터를 사용하여 클라이언트와 서버 간의 바인딩을 작성할 수 있습니다.
  • 서버 프로그램의 위치에 대한 이름 서비스 데이터베이스 쿼리

이 섹션에서는 다음 topics 이러한 두 가지 기술에 대한 정보를 제공합니다.

문자열 바인딩 사용

애플리케이션은 문자열에 저장된 정보에서 바인딩을 만들 수 있습니다. 클라이언트 애플리케이션은 이 정보를 문자열로 구성한 다음 RpcBindingFromStringBinding 함수를 호출합니다. 클라이언트는 서버를 식별하기 위해 다음 정보를 제공해야 합니다.

(개체 UUID 및 엔드포인트 정보는 선택 사항입니다.)

다음 예제에서는 pszNetworkAddress 매개 변수 및 기타 매개 변수에 포함된 백슬래시가 포함됩니다. 백슬래시는 C 프로그래밍 언어의 이스케이프 문자입니다. 각 단일 리터럴 백슬래시 문자를 나타내려면 두 개의 백슬래시가 필요합니다. 문자열 바인딩 구조는 서버 이름 앞에 오는 두 개의 리터럴 백슬래시 문자를 나타내기 위해 4개의 백슬래시 문자를 포함해야 합니다.

다음 예제에서는 sprintf_s 함수가 문자열을 처리한 후 문자열 바인딩 데이터 구조에 4개의 리터럴 백슬래시 문자가 표시되도록 서버 이름 앞에 8개의 백슬래시가 있어야 합니다.

/* client application */

char * pszUuid = "6B29FC40-CA47-1067-B31D-00DD010662DA";
char * pszProtocol = "ncacn_np";
char * pszNetworkAddress = "\\\\\\\\servername";
char * pszEndpoint = "\\\\pipe\\\\pipename";
char * pszString;
 
int len = 0;
 
len  = sprintf_s(pszString, strlen(pszUuid), "%s", pszUuid);
len += sprintf_s(pszString + len, strlen(pszProtocolSequence) + 2, "@%s:",
    pszProtocolSequence);
if (pszNetworkAddress != NULL)
    len += sprintf_s(pszString + len, strlen(pszNetworkAddress), "%s",
    pszNetworkAddress);
len += sprintf_s(pszString + len, strlen(pszEndpoint) + 2, "[%s]", pszEndpoint);

다음 예제에서는 문자열 바인딩이 다음과 같이 표시됩니다.

6B29FC40-CA47-1067-B31D-00DD010662DA@ncacn_np:\\\\servername[\\pipe\\pipename]

그런 다음, 클라이언트는 RpcBindingFromStringBinding을 호출하여 바인딩 핸들을 가져옵니다.

RPC_BINDING_HANDLE hBinding;
 
status = RpcBindingFromStringBinding(pszString, &hBinding);
//...

편의 함수인 RpcStringBindingComposeRpcBindingFromStringBinding에 대한 호출에 대한 올바른 구문으로 개체 UUID, 프로토콜 시퀀스, 네트워크 주소 및 엔드포인트를 어셈블합니다. 각 프로토콜 시퀀스에 대한 앰퍼샌드, 콜론 및 다양한 구성 요소를 올바른 위치에 배치하는 것에 대해 걱정할 필요가 없습니다. 문자열을 함수에 대한 매개 변수로 제공하기만 하면 됩니다. 런타임 라이브러리는 문자열 바인딩에 필요한 메모리도 할당합니다.

char * pszNetworkAddress = "\\\\server";
char * pszEndpoint = "\\pipe\\pipename";
status = RpcStringBindingCompose(
            pszUuid,
            pszProtocolSequence,
            pszNetworkAddress,
            pszEndpoint,
            pszOptions,
            &pszString);
//...
status = RpcBindingFromStringBinding(
            pszString,
            &hBinding);
//...

또 다른 편의 함수인 RpcBindingToStringBinding은 바인딩 핸들을 입력으로 사용하고 해당 문자열 바인딩을 생성합니다.

이름 서비스 데이터베이스에서 가져오기

서비스 데이터베이스는 무엇보다도 바인딩 핸들 및 UUID를 저장합니다. 클라이언트 애플리케이션은 서버에 바인딩해야 하는 경우 둘 중 하나 또는 둘 다를 검색할 수 있습니다. 이름 서비스가 저장하는 정보 및 스토리지 형식에 대한 자세한 내용은 RPC 이름 서비스 데이터베이스를 참조하세요.

RPC 라이브러리는 클라이언트 프로그램에서 이름 서비스 데이터베이스를 검색하는 데 사용할 수 있는 두 가지 함수 집합을 제공합니다. 한 집합의 이름은 RpcNsBindingImport로 시작합니다. 다른 집합의 이름은 RpcNsBindingLookup으로 시작합니다. 두 함수 그룹의 차이점은 RpcNsBindingImport 함수가 호출당 단일 바인딩 핸들을 반환하고 RpcNsBindingLookup 함수는 호출당 핸들 그룹을 반환한다는 것입니다.

RpcNsBindingImport 함수를 사용하여 검색을 시작하려면 먼저 다음 코드 조각과 같이 RpcNsBindingImportBegin을 호출합니다.

RPC_STATUS status;
RPC_NS_HANDLE hNameServiceHandle;
 
status = RpcNsBindingImportBegin(
    RPC_C_NS_SYNTAX_DEFAULT,
    NULL,
    MyInterface_v1_0_c_ifspec,
    NULL,
    &hNameServiceHandle);

RPC 함수는 이름 서비스 데이터베이스를 검색할 때 검색을 시작할 장소가 필요합니다. RPC 용어에서 이를 항목 이름이라고 합니다. 클라이언트 프로그램에서 항목 이름을 두 번째 매개 변수로 RpcNsBindingImportBegin에 전달합니다. 전체 이름 서비스 데이터베이스를 검색하려는 경우 이 매개 변수는 NULL 일 수 있습니다. 또는 서버 항목 이름을 전달하여 서버 항목을 검색하거나 그룹 항목 이름을 전달하여 그룹 항목을 검색할 수 있습니다. 항목 이름을 전달하면 검색이 해당 항목의 내용으로 제한됩니다.

앞의 예제에서 RPC_C_NS_SYNTAX_DEFAULT 값은 RpcNsBindingImportBegin에 첫 번째 매개 변수로 전달됩니다. 그러면 기본 항목 이름 구문이 선택됩니다. 현재 지원되는 유일한 항목 이름 구문입니다.

클라이언트 애플리케이션은 이름 서비스 데이터베이스에서 인터페이스 이름, UUID 또는 둘 다를 검색할 수 있습니다. 이름으로 인터페이스를 검색하려면 MIDL 컴파일러가 IDL 파일에서 생성하는 전역 인터페이스 변수를 RpcNsBindingImportBegin에 세 번째 매개 변수로 전달합니다. 헤더 파일에서 MIDL 컴파일러가 클라이언트 스텁을 생성할 때 생성한 선언을 찾을 수 있습니다. 클라이언트 프로그램이 UUID로만 검색되도록 하려면 세 번째 매개 변수를 NULL로 설정합니다.

이름 서비스 데이터베이스에서 UUID를 검색할 때 RpcNsBindingImportBegin 의 네 번째 매개 변수를 검색하려는 UUID로 설정합니다. UUID를 검색하지 않는 경우 이 매개 변수를 NULL로 설정합니다.

RpcNsBindingImportBegin 함수는 다섯 번째 매개 변수를 통해 이름 서비스 검색 컨텍스트 핸들의 주소를 전달합니다. 이 매개 변수를 다른 RpcNsBindingImport 함수에 전달합니다.

특히 클라이언트 애플리케이션에서 호출하는 다음 함수는 RpcNsBindingImportNext입니다. 클라이언트 프로그램은 이 함수를 사용하여 이름 서비스 데이터베이스에서 호환되는 바인딩 핸들을 검색합니다. 다음 코드 조각은 이 함수를 호출하는 방법을 보여 줍니다.

RPC_STATUS status;
RPC_BINDING_HANDLE hBindingHandle;
// The variable hNameServiceHandle is a valid name service search 
// context handle obtained from the RpcNsBindingBegin function.
 
status = RpcNsBindingImportNext(hNameServiceHandle, &hBindingHandle);

바인딩 핸들을 가져오기 위해 RpcNsBindingImportNext 함수를 호출하면 클라이언트 애플리케이션에서 수신한 핸들이 허용되는지 확인할 수 있습니다. 그렇지 않은 경우 클라이언트 프로그램은 루프를 실행하고 RpcNsBindingImportNext 를 다시 호출하여 이름 서비스에 더 적절한 핸들이 포함되어 있는지 확인할 수 있습니다. RpcNsBindingImportNext에 대한 각 호출에 대해 RpcNsBindingFree에 대한 해당 호출이 있어야 합니다. 검색이 완료되면 RpcNsBindingImportDone 함수를 호출하여 조회 컨텍스트를 해제합니다.

클라이언트 애플리케이션에 허용 가능한 바인딩 핸들이 있으면 서버 애플리케이션이 실행 중인지 확인하는 검사 합니다. 클라이언트에서 이 확인을 수행하는 데 사용할 수 있는 두 가지 방법이 있습니다. 첫 번째는 클라이언트 인터페이스에서 함수를 호출하는 것입니다. 서버 프로그램이 실행 중인 경우 호출이 완료됩니다. 그렇지 않으면 호출이 실패합니다. 서버가 실행 중인지 확인하는 더 좋은 방법은 RpcEpResolveBinding을 호출한 다음 RpcMgmtIsServerListening을 호출하는 것입니다. 이름 서비스 데이터베이스에 대한 자세한 내용은 RPC 이름 서비스 데이터베이스를 참조하세요.