Inter-Object 통신

COM은 클라이언트가 동일한 프로세스, 동일한 컴퓨터 또는 다른 컴퓨터에서 해당 개체가 실행되는 위치에 관계없이 개체와 투명하게 통신할 수 있도록 설계되었습니다. 모든 유형의 개체와 개체 클라이언트 및 개체 서버 모두에 대해 단일 프로그래밍 모델을 제공합니다.

클라이언트의 관점에서 모든 개체는 인터페이스 포인터를 통해 액세스됩니다. 포인터는 in-process여야 합니다. 실제로 인터페이스 함수에 대한 모든 호출은 항상 프로세스 내 코드의 일부 부분에 먼저 도달합니다. 개체가 진행 중이면 호출이 시스템 인프라 코드가 개입되지 않고 직접 연결됩니다. 개체가 out-of-process인 경우 호출은 먼저 COM 또는 개체에서 제공하는 "프록시" 개체(구현자가 원하는 경우)에 도달합니다. 프록시 패키지는 매개 변수(인터페이스 포인터 포함)를 호출하고 다른 프로세스 또는 개체 구현이 있는 다른 컴퓨터에 적절한 원격 프로시저 호출(또는 사용자 지정 생성 프록시의 경우 다른 통신 메커니즘)을 생성합니다. 프로세스 경계를 넘어 전송하기 위한 포인터를 패키징하는 이 프로세스를 마샬링이라고 합니다.

서버의 관점에서 개체의 인터페이스 함수에 대한 모든 호출은 해당 인터페이스에 대한 포인터를 통해 이루어집니다. 다시 말하지만 포인터는 단일 프로세스에서만 컨텍스트를 가지며 호출자는 항상 프로세스 내 코드의 일부여야 합니다. 개체가 진행 중인 경우 호출자는 클라이언트 자체입니다. 그렇지 않으면 호출자는 COM 또는 개체 자체에서 제공하는 "스텁" 개체입니다. 스텁은 클라이언트 프로세스의 "프록시"에서 원격 프로시저 호출(또는 사용자 지정 생성 프록시의 경우 다른 통신 메커니즘)을 수신하고 매개 변수를 숨기지 않고 서버 개체에서 적절한 인터페이스를 호출합니다. 클라이언트와 서버 모두의 관점에서 볼 때 항상 다른 In-process 코드와 직접 통신합니다.

COM은 표준 마샬링이라고 하는 마샬링 구현을 제공합니다. 이 구현은 대부분의 개체에서 매우 잘 작동하며 프로그래밍 요구 사항을 크게 줄여 마샬링 프로세스를 효과적으로 투명하게 만듭니다.

그러나 COM의 프로세스 투명성 구현과 인터페이스를 명확하게 분리하면 어떤 상황에서는 방해가 될 수 있습니다. 클라이언트의 관점에서 함수에 중점을 둔 인터페이스의 디자인은 때때로 네트워크를 통해 해당 인터페이스의 효율적인 구현과 충돌하는 디자인 결정으로 이어질 수 있습니다. 이와 같은 경우 필요한 것은 순수한 프로세스 투명성이 아니라 "신경 쓸 필요가 없는 한 프로세스 투명성"입니다. COM은 개체 구현자가 사용자 지정 마샬링 ( IMarshal 마샬링이라고도 함)을 지원할 수 있도록 하여 이 기능을 제공합니다. 실제로 표준 마샬링은 사용자 지정 마샬링의 instance 개체에 사용자 지정 마샬링이 필요하지 않을 때 사용되는 기본 구현입니다.

사용자 지정 마샬링을 구현하여 개체가 로컬 액세스에서 수행되고 클라이언트에 완전히 투명하게 사용되는 것과 네트워크 간에 사용될 때 다른 작업을 수행할 수 있도록 할 수 있습니다. 이 아키텍처를 사용하면 네트워크 성능 문제와 관계없이 클라이언트/개체 인터페이스를 디자인한 다음 나중에 설정된 디자인을 방해하지 않고 네트워크 성능 문제를 해결할 수 있습니다.

COM은 구성 요소의 구조화 방법을 지정하지 않습니다. 상호 작용하는 방법을 지정합니다. COM은 구성 요소의 내부 구조에 대한 우려를 프로그래밍 언어 및 개발 환경에 둡니다. 반대로 프로그래밍 환경에는 즉시 애플리케이션 외부에서 개체를 사용하기 위한 설정된 표준이 없습니다. 예를 들어 Microsoft Visual C++ 애플리케이션 내에서 개체를 조작하는 데 매우 잘 작동하지만 애플리케이션 외부의 개체 작업에 대한 지원은 없습니다. 일반적으로 다른 모든 프로그래밍 언어는 이와 동일합니다. 따라서 네트워크 전체의 상호 운용성을 제공하기 위해 언어 독립적 인터페이스를 통해 COM은 프로그래밍 언어가 중단되는 위치를 선택합니다.

vtbl 구조체의 이중 간접 참조는 함수 포인터 테이블의 포인터가 실제 개체의 실제 구현을 직접 가리킬 필요가 없음을 의미합니다. 이것이 프로세스 투명성의 핵심입니다.

개체가 클라이언트 프로세스에 직접 로드되는 In-Process 서버의 경우 테이블의 함수 포인터는 실제 구현을 직접 가리킵니다. 이 경우 클라이언트에서 인터페이스 메서드로의 함수 호출은 실행 컨트롤을 메서드로 직접 전송합니다. 그러나 메모리에 대한 포인터를 프로세스 간에 공유할 수 없으므로 원격 개체는 물론 로컬에서 작동할 수 없습니다. 그럼에도 불구하고 클라이언트는 실제 구현을 호출하는 것처럼 인터페이스 메서드를 호출할 수 있어야 합니다. 따라서 클라이언트는 호출을 수행하여 일부 개체의 메서드로 컨트롤을 균일하게 전송합니다.

클라이언트는 항상 일부 in-process 개체에서 인터페이스 메서드를 호출합니다. 실제 개체가 로컬 또는 원격인 경우 프록시 개체를 호출한 다음 실제 개체에 대한 원격 프로시저 호출을 만듭니다.

그렇다면 실제로 실행되는 메서드는 무엇인가요? 정답은 out-of-process 인터페이스에 대한 호출이 있을 때마다 각 인터페이스 메서드가 프록시 개체에 의해 구현된다는 것입니다. 프록시 개체는 항상 호출되는 개체를 대신하여 작동하는 in-process 개체입니다. 이 프록시 개체는 실제 개체가 로컬 또는 원격 서버에서 실행 중임을 알고 있습니다.

프록시 개체는 일부 데이터 패킷에서 함수 매개 변수를 패키지하고 로컬 또는 원격 개체에 대한 RPC 호출을 생성합니다. 해당 패킷은 로컬 또는 원격 컴퓨터의 서버 프로세스에 있는 스텁 개체에 의해 선택되며, 매개 변수의 압축을 풀고 메서드의 실제 구현을 호출합니다. 해당 함수가 반환되면 스텁은 모든 out 매개 변수와 반환 값을 패키지하고 프록시로 다시 전송하여 압축을 풀고 원래 클라이언트에 반환합니다.

따라서 클라이언트와 서버는 항상 모든 것이 진행 중인 것처럼 서로 통신합니다. 클라이언트의 모든 호출과 서버에 대한 모든 호출은 어느 시점에서 처리 중입니다. 그러나 vtbl 구조에서는 COM과 같은 일부 에이전트가 모든 함수 호출과 함수의 모든 반환을 가로챌 수 있으므로 해당 에이전트는 필요에 따라 해당 호출을 RPC 호출로 리디렉션할 수 있습니다. In-Process 호출은 out-of-process 호출보다 빠르지만 프로세스 차이는 클라이언트와 서버에 완전히 투명합니다.

자세한 내용은 아래 항목을 참조하세요.

COM 클라이언트 및 서버

인터페이스 마샬링