서버 호스트 시스템은 분산 애플리케이션의 서버 프로그램을 실행하는 컴퓨터입니다. 네트워크에 하나 이상의 서버 호스트 시스템이 있을 수 있습니다. 클라이언트 프로그램에서 연결할 서버를 찾는 방법은 프로그램의 요구 사항에 따라 달라집니다.
서버 호스트 시스템을 찾는 방법에는 두 가지가 있습니다.
- 클라이언트 소스 코드, 환경 변수 또는 애플리케이션별 구성 파일의 문자열에 저장된 정보를 사용합니다. 클라이언트 애플리케이션은 문자열의 데이터를 사용하여 클라이언트와 서버 간에 바인딩을 작성할 수 있습니다.
- 서버 프로그램의 위치에 대한 이름 서비스 데이터베이스 쿼리
이 섹션에서는 다음 항목에서 이러한 두 기술에 대한 정보를 제공합니다.
문자열 바인딩 사용
애플리케이션은 문자열에 저장된 정보에서 바인딩을 만들 수 있습니다. 클라이언트 애플리케이션은 이 정보를 문자열로 구성한 다음 RpcBindingFromStringBinding 함수를 호출합니다. 클라이언트는 서버를 식별하기 위해 다음 정보를 제공해야 합니다.
- 인터페이스 이름, 개체의 GUID(Globally Unique Identifier) 또는 개체의 UUID입니다. 자세한 내용은 인터페이스 UUID 생성 및 문자열 UUID참조하세요.
- 통신할 전송 유형(예: 명명된 파이프 또는 TCP/IP)입니다. 자세한 내용은 Essential RPC 바인딩 용어 및 프로토콜 시퀀스 선택을 참조하세요.
- 네트워크 주소 또는 서버 호스트 컴퓨터의 이름입니다.
- 서버 호스트 컴퓨터의 서버 프로그램의 엔드포인트입니다. 자세한 내용은 엔드포인트 찾기및 엔드포인트지정을 참조하세요.
(개체 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);
//...
편리한 함수인 RpcStringBindingCompose는 개체 UUID, 프로토콜 시퀀스, 네트워크 주소 및 엔드포인트를 올바른 구문으로 어셈블하여 호출에 적합하게 준비하고, 이는 RpcBindingFromStringBinding에 사용됩니다. 각 프로토콜 시퀀스에 대한 앰퍼샌드, 콜론 및 다양한 구성 요소를 올바른 위치에 배치하는 것에 대해 걱정할 필요가 없습니다. 함수에 매개 변수로 문자열을 제공합니다. 런타임 라이브러리는 문자열 바인딩에 필요한 메모리도 할당합니다.
char * pszNetworkAddress = "\\\\server";
char * pszEndpoint = "\\pipe\\pipename";
status = RpcStringBindingCompose(
pszUuid,
pszProtocolSequence,
pszNetworkAddress,
pszEndpoint,
pszOptions,
&pszString);
//...
status = RpcBindingFromStringBinding(
pszString,
&hBinding);
//...
RpcBindingToStringBinding또 다른 편리한 함수는 바인딩 핸들을 입력으로 사용하고 해당 문자열 바인딩을 생성합니다.
이름 서비스 데이터베이스에서 가져오기
이름 서비스 데이터베이스는 바인딩 핸들 및 UUID 등을 저장합니다. 클라이언트 애플리케이션은 서버에 바인딩해야 하는 경우 둘 중 하나 또는 둘 다를 검색할 수 있습니다. 이름 서비스가 저장하는 정보 및 스토리지 형식에 대한 자세한 내용은 RPC Name Service Database 참조하세요.
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 또는 둘 다를 검색할 수 있습니다. 이름으로 인터페이스를 검색하려면 IDL 파일에서 MIDL 컴파일러가 생성하는 전역 인터페이스 변수를 세 번째 매개변수로 전달하여 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 이름 서비스 데이터베이스 참조하세요.