Comunicação Inter-Object
O COM foi projetado para permitir que os clientes se comuniquem de forma transparente com objetos, independentemente de onde esses objetos estão sendo executados, no mesmo processo, no mesmo computador ou em um computador diferente. Isso fornece um único modelo de programação para todos os tipos de objetos e para clientes de objeto e servidores de objetos.
Do ponto de vista de um cliente, todos os objetos são acessados por meio de ponteiros de interface. Um ponteiro deve estar em processo. Na verdade, qualquer chamada para uma função de interface sempre atinge alguma parte do código em processo primeiro. Se o objeto estiver em processo, a chamada o atingirá diretamente, sem nenhum código de infraestrutura do sistema interveniente. Se o objeto estiver fora do processo, a chamada atingirá primeiro o que é chamado de objeto "proxy" fornecido pelo COM ou pelo objeto (se o implementador desejar). Os pacotes de proxy chamam parâmetros (incluindo quaisquer ponteiros de interface) e geram a chamada de procedimento remoto apropriada (ou outro mecanismo de comunicação no caso de proxies gerados personalizados) para o outro processo ou outro computador em que a implementação do objeto está localizada. Esse processo de empacotamento de ponteiros para transmissão entre limites de processo é chamado marshaling.
Do ponto de vista de um servidor, todas as chamadas para as funções de interface de um objeto são feitas por meio de um ponteiro para essa interface. Novamente, um ponteiro tem contexto apenas em um único processo e o chamador sempre deve ser uma parte do código em processo. Se o objeto estiver em processo, o chamador será o próprio cliente. Caso contrário, o chamador é um objeto "stub" fornecido pelo COM ou pelo próprio objeto. O stub recebe a chamada de procedimento remoto (ou outro mecanismo de comunicação no caso de proxies gerados personalizados) do "proxy" no processo do cliente, desmarca os parâmetros e chama a interface apropriada no objeto do servidor. Nos pontos de vista de clientes e servidores, eles sempre se comunicam diretamente com algum outro código em processo.
O COM fornece uma implementação de marshaling, conhecida como de marshaling padrão. Essa implementação funciona muito bem para a maioria dos objetos e reduz consideravelmente os requisitos de programação, tornando o processo de marshaling efetivamente transparente.
No entanto, a separação clara da interface da implementação da transparência do processo do COM pode atrapalhar algumas situações. O design de uma interface que se concentra em sua função do ponto de vista do cliente às vezes pode levar a decisões de design que entram em conflito com a implementação eficiente dessa interface em uma rede. Em casos como este, o que é necessário não é transparência pura do processo, mas "transparência do processo, a menos que você precise se importar". O COM fornece essa funcionalidade permitindo que um implementador de objetos dê suporte a de marshaling personalizado (também chamado marshaling de IMarshal). O marshaling padrão é, de fato, uma instância de marshaling personalizado; é a implementação padrão usada quando um objeto não requer marshaling personalizado.
Você pode implementar o marshaling personalizado para permitir que um objeto execute ações diferentes quando usado em uma rede do que ele usa em acesso local e é completamente transparente para o cliente. Essa arquitetura possibilita projetar interfaces cliente/objeto sem considerar problemas de desempenho de rede e, posteriormente, resolver problemas de desempenho de rede sem interromper o design estabelecido.
O COM não especifica como os componentes são estruturados; especifica como eles interagem. O COM deixa a preocupação com a estrutura interna de um componente para linguagens de programação e ambientes de desenvolvimento. Por outro lado, os ambientes de programação não têm padrões definidos para trabalhar com objetos fora do aplicativo imediato. O Microsoft Visual C++, por exemplo, funciona muito bem para manipular objetos dentro de um aplicativo, mas não tem suporte para trabalhar com objetos fora do aplicativo. Em geral, todas as outras linguagens de programação são as mesmas nesse sentido. Portanto, para fornecer interoperabilidade em toda a rede, o COM, por meio de interfaces independentes de linguagem, continua de onde as linguagens de programação param.
O redirecionamento duplo da estrutura vtbl significa que os ponteiros na tabela de ponteiros de função não precisam apontar diretamente para a implementação real no objeto real. Este é o coração da transparência do processo.
Para servidores em processo, em que o objeto é carregado diretamente no processo do cliente, os ponteiros da função na tabela apontam diretamente para a implementação real. Nesse caso, uma chamada de função do cliente para um método de interface transfere diretamente o controle de execução para o método. No entanto, isso não pode funcionar para objetos locais, muito menos remotos, porque ponteiros para memória não podem ser compartilhados entre processos. No entanto, o cliente deve ser capaz de chamar métodos de interface como se estivesse chamando a implementação real. Assim, o cliente transfere uniformemente o controle para um método em algum objeto fazendo a chamada.
Um cliente sempre chama métodos de interface em algum objeto em processo. Se o objeto real for local ou remoto, a chamada será feita para um objeto proxy, o que, em seguida, fará uma chamada de procedimento remoto para o objeto real.
Então, qual método é realmente executado? A resposta é que sempre que há uma chamada para uma interface fora de processo, cada método de interface é implementado por um objeto proxy. O objeto proxy é sempre um objeto em processo que atua em nome do objeto que está sendo chamado. Esse objeto proxy sabe que o objeto real está em execução em um servidor local ou remoto.
O objeto proxy empacota os parâmetros de função em alguns pacotes de dados e gera uma chamada RPC para o objeto local ou remoto. Esse pacote é captado por um objeto stub no processo do servidor no computador local ou remoto, que descompacta os parâmetros e faz a chamada para a implementação real do método. Quando essa função retorna, o stub empacota todos os parâmetros externos e o valor retornado e o envia de volta para o proxy, o que os descompacta e os retorna para o cliente original.
Assim, o cliente e o servidor sempre conversam entre si como se tudo estivesse em processo. Todas as chamadas do cliente e todas as chamadas para o servidor estão, em algum momento, em processo. Mas como a estrutura vtbl permite que algum agente, como COM, intercepte todas as chamadas de função e todos os retornos das funções, esse agente pode redirecionar essas chamadas para uma chamada RPC conforme necessário. Embora as chamadas em processo sejam mais rápidas do que as chamadas fora de processo, as diferenças de processo são completamente transparentes para o cliente e o servidor.
Para obter mais informações, consulte os seguintes tópicos:
Tópicos relacionados