Você está na página 1de 11

.

NET Remoting
Um estudo ao suporte de invocações em objectos remotos na plataforma .NET
Milton Moura Ricardo Seabra
Faculdade de Ciências e Tecnologia Faculdade de Ciências e Tecnologia
Universidade Nova de Lisboa Universidade Nova de Lisboa
Pós-Graduação em Enga Informática Licenciatura em Enga Informática
miltonmoura@gmail.com ricardo.seabra@gmail.com

RESUMO infra-estruturas deste tipo, como os stubs, o processo de


Existe hoje em dia um número considerável de tecnologias marshaling e a IDL [1].
orientadas para a programação de sistemas de objectos dis- A restante plataforma .NET é constituı́da por um ambi-
tribuı́dos, como são exemplo disso o CORBA, o Java/RMI, o ente controlado de execução de código, designado por CLR
DCOM e, mais recentemente, o .NET Remoting. Qualquer (Common Language Runtime), um gestor de memória, re-
uma delas oferece um agregado de serviços e funcionalidades sponsável pela recolha automática de referências não uti-
que diferem na sua abordagem e implementação, tornando- lizadas, um sistema de tipos unificado (Common Type Sys-
as mais ou menos complexas e apropriadas para determina- tem) que permite a interoperabilidade entre objectos imple-
dos cenários de utilização. mentados em diferentes linguagens de programação, compi-
Este trabalho resulta de uma análise ao suporte de in- ladas por uma ferramenta que implemente a CLS (Common
vocações em objectos remotos na plataforma de desenvolvi- Language Specification), e um conjunto de APIs, separados
mento .NET, tendo como ambiente de execução a imple- em módulos lógicos, que enriquece o modelo de objectos base
mentação multi-plataforma da especificação CLI denomi- fornecido [5].
nada Mono, e pretende expor os vários aspectos dos serviços
disponbilizados pelo componente .NET Remoting, bem como 2. .NET REMOTING
a sua arquitectura e funcionamento interno. Integrado na especificação da plataforma Microsoft .NET,
Numa vertente práctica, são apresentados alguns exemp- o componente .NET Remoting permite o desenvolvimento
los de diferentes técnicas normalmente utilizadas em ambi- de aplicações distribuı́das, onde os objectos participantes
entes de sistemas de objectos distribuı́dos, com o objectivo podem ser executados em máquinas e processos diferentes e
de oferecer assim uma visão comparativa deste suporte em em dominios aplicacionais distintos.
relação a outros já estudados. Na génese do .NET Remoting está uma implementação
abstracta de comunicação entre processos que separa os ob-
1. INTRODUÇÃO jectos remotos e seus potenciais clientes do mecanismo de
As tecnologias de suporte aos sistemas distribuı́dos de ob- comunicação entre si, tornando-se assim uma plataforma
jectos permitem que componentes em execução numa de- flexı́vel e extensı́vel, onde os protocolos de comunicação e
termina máquina sejam acedidos por aplicações ou objectos formatos de serialização podem ser facilmente alterados. É
em execução noutras máquinas distintas. Tecnologias como também agnóstica ao modelo da aplicação, possibilitando a
o CORBA, o Java/RMI, o DCOM e o .NET Remoting são interoperabilidade entre aplicações Web, serviços de sistema
exemplos de sistemas deste tipo e, apesar de estarem imple- ou programas executados na consola.
mentados de forma muito diferente e com funcionalidades A plataforma disponibiliza ainda um conjunto de serviços
distintas, mantêm algumas semelhanças: comuns em ambientes de middleware, como o suporte à ac-
tivação de objectos remotos, gestão do seu ciclo de vida e
• Os objectos têm uma identidade única e podem ter um segurança nos canais de mensagens.
estado de execução.
2.1 Meta-Modelo de Objectos
• A utilização de objectos remotos tem a mesma semãntica e Definição de Interfaces
dos objectos locais. O código executado na plataforma .NET tem vários nı́veis
de isolamento, sendo que num processo da CLR podem estar
• Estão associados a um modelo de componentes, onde em execução vários domı́nios aplicacionais. Em qualquer
os detalhes de implementação estão escondidos. domı́nio aplicacional são dadas as seguintes garantias:
• Têm modelos de tolerância a falhas bem definidos. 1. Uma aplicação pode ser parada de forma indepen-
dente.
A implementação de suporte à invocação de objectos re-
motos no .NET Remoting é semelhante à do Java/RMI [7] 2. Uma aplicação não pode aceder directamente a código
em muitos aspectos, pois ambos têm como base a especi- e recursos de outra aplicação.
ficação de Birrel et al [2] para RPC’s (Remote Procedure
Calls), que introduziu os conceitos básicos utilizados nas 3. Uma falha na aplicação não afecta as restantes aplicações.

1
4. A configuração da aplicação determina o local de onde Os tipos de objectos remotos podem ser classificados de
o código é carregado e a sua versão. acordo com três categorias: marshal-by-value, marshal-by-
reference ou context-bound. As instâncias dos tipos marshal-
Um domı́nio aplicacional pode ainda ser dividido em con- by-value podem ser enviadas entre domı́nios aplicacionais
textos, que asseguram uma série de restrições e semântica de através de um processo de serialização, que corresponde à
segurança no acesso aos objectos que neles se encontrem em codificação do estado actual de um objecto numa sequência
execução. Por omissão, todo o domı́nio aplicacional contém de bits. A recepção de um objecto deste tipo resulta na
pelo menos um contexto, onde são criados todos os objec- criação de uma cópia no destino, com o mesmo estado do
tos, excepto aqueles que necessitam de um novo contexto objecto original. Os objectos deste tipo são caracteriza-
especializado. dos por um atributo especificado na sua definição, o atrib-
uto Serializable. No entanto, é possı́vel que um objecto
definido com este atributo contenha propriedades que não
se destinem a ser transmitidas. Para tal, deve-se colocar o
atributo NonSerializable no campo em causa.
Os objectos do tipo marshal-by-reference são utilizados
quando se pretende manter uma única instância desse tipo
acessı́vel num determinado domı́nio aplicacional, sendo pas-
sada uma referência dessa instância aos seus clientes, em
vez de uma cópia serializada. Assim, para que os objec-
tos possam ser acedidos remotamente, estes têm de derivar
do tipo MarshalByRefObject (ver Figura 2), de forma a su-
portar essa funcionalidade. As referências envolvidas neste
processo são objectos do tipo ObjRef.

[Serializable]
public abstract class MarshalByRefObject
{
Figura 1: Nı́veis de isolamento da CLR. protected MarshalByRefObject () { }

internal Identity GetObjectIdentity (


2.1.1 Objectos MarshalByRefObject obj,
O .NET Remoting possbilita a invocação de métodos so- out bool IsClient
bre objectos remotos, em execução num CLR host. É in- );
diferente ao sistema a linguagem em que estão implementa-
dos os objectos servidores e objectos clientes, podendo esta [NonSerialized]
ser distinta. O sistema unificado de tipos da plataforma gere internal ServerIdentity ObjectIdentity
a representação interna dos objectos e garante assim a sua { get; set; }
interoperabilidade.
A invocação remota de métodos depende da obtenção de public virtual ObjRef CreateObjRef (Type type);
uma referência para o objecto remoto, referência esta que public virtual object GetLifetimeService ();
contém uma série de meta-dados necessários para que o public virtual object InitializeLifetimeService ();
cliente efectue a invocação de forma transparente, utilizando }
uma semântica de acesso idêntica à dos objectos locais.
A obtenção dessa referência é levado a cabo através de um
Figura 2: Excerto da classe MarshalByRefObject
canal de comunicações estabelecido com o servidor, desig-
nado por um URI (Universal Resource Identifier ) de acesso
Por último, os tipos context-bound constituem uma espe-
único. Ao iniciar, é da responsabilidade do servidor registar
cialização do objecto remoto tı́pico, passado por referência,
ambos estas propriedades na plataforma.
que neste caso está restrito ao contexto de execução em que
é instanciado. Isto significa que o seu acesso, inclusive a par-
2.1.2 Tipos
tir do mesmo domı́nio aplicacional, envolve sempre o envio
Com o objectivo de possibilitar a interacção entre objectos de uma referência remota para os objectos clientes, em vez
residentes em diferentes nı́veis de isolamento da plataforma, da invocação local normal que seria de esperar em situações
os tipos de objectos objectos podem ser classificados de re- deste tipo. Essa funcionalidade é adquirida derivando do
motos ou não-remotos. Um tipo é considerado remoto se: tipo ContextBoundObject.
Os restantes tipos não-remotos definidos para a plataforma
1. As suas instâncias podem atravessar os nı́veis de iso- .NET são suportados pela API de Remoting de forma trans-
lamento da plataforma. parente, possibilitando a utilização de qualquer classe, in-
terface, enumeração e objecto, sem quaisquer limitações.
2. Outros objectos podem aceder a instâncias do tipo, Partindo do princı́pio que tanto os clientes como os ob-
atravessando os nı́veis de isolamento da plataforma. jectos servidor estão contidos em plataformas de execução
idênticas, isto é, em CLRs baseadas numa mesma versão
Qualquer tipo de objecto que não satisfaça estas pro- de implementação, a interoperabilidade a nı́vel de tipos de
priedades, é não-remoto. dados está solucionada à partida.

2
2.1.3 Atributos delegate string MyDelegate(int myValue);
string DoSomething(int myValue);
Um tipo de objecto remoto pode definir atributos, desig-
nados por propriedades na plataforma .NET, e especificar se MyDelegate md = new MyDelegate(DoSomething);
estes são só de leitura ou de leitura e escrita. No entanto, a
sua implementação interna, forma de acesso e representação // invocaç~
ao assı́ncrona
são em tudo idênticas aos dos métodos. IAsyncResult ar = md.BeginInvoke(
interface IRemoteObject someValue, null, null);
{
int MyRemoteMethod(); // obtenç~
ao do resultado
// propriedade só de leitura string result = md.EndInvoke(ar);
double MyFloatProperty { get; }
// propriedade de leitura-escrita
Figura 4: Exemplo de invocação assı́ncrona
int MyIntProperty { get; set; }
}
retorno da função. É também suportado um modo de in-
vocação assı́ncrona num só sentido, ou seja, os métodos não
Figura 3: Exemplo de definição de propriedades
podem possuir retorno ou parâmetros de saı́da.
Apesar de existir uma API de reflexão na especificação
da CLI (System.Reflection), esta não está integrada com
2.1.4 Operações o Remoting de forma a possibilitar a invocação dinâmica
Designados por métodos, as operações em Remoting po- de operações. Está portanto limitada à invocação estática
dem ser invocadas desde que declaradas como públicas na e dependente do acesso à definição dos tipos dos objectos
implementação do tipo de objecto remoto. Caso o objecto num assembly local ou registado na GAC (Global Assembly
remoto seja uma implementação de um ou mais interfaces, Cache).
então todos os métodos implementados, necessários para
satisfazer o contrato, são públicos. 2.1.6 Tratamento de erros
A semântica de invocação das operações remotas é muito O tratamento de erros, à semelhança do que acontece
semelhante à dos métodos locais, uma vez que os parâmetros na restante plataforma, é efectuada através da propagação
podem ser passados por referência ou por valor. A pas- de excepções, objectos do tipo Exception que deverão ser
sagem de um parâmetro por referência significa que é pas- definidos como serializáveis, de forma a poderem ser trans-
sado um apontador com a informação necessária para que formadas e enviados pelos canais de comunicação definidos
a operação o manipule, tal como a sua localização e outros entre os objectos remotos e clientes envolvidos. Em partic-
dados necessários. A passagem de objectos por valor resulta ular, os erros com origem na infra-estrutura de Remoting,
na criação de uma cópia no contexto de execução do método lançam apenas um tipo de excepção: o RemotingException.
invocado, idêntica à do objecto submetido. Uma excepção deste tipo pode ser levantada por inúmeras
No entanto, quando estão envolvidos objectos remotos, a razões, entre as quais:
sua passagem como parâmetro de um método remoto de-
pende do seu tipo, mais precisamente, se este é marshal-by- • É instanciado um tipo de objecto remoto que não deriva
reference ou marshal-by-value. de MarshalByRefObject.

2.1.5 Invocações • Especificação inválida do ponto de acesso de um tipo


de objecto remoto, isto é, o URI está mal formado.
A semântica de invocações nesta plataforma é do tipo at-
most-once, o que significa que a recepção de uma excepção • Protocolos de comunicação diferentes entre os clientes
resultante de uma invocação remota indica que o método e os objectos servidor.
alvo poderá não ter sido executado. Por outro lado, a inex-
istência de erros constitui uma garantia de que a operação • A invocação de operações sobre objectos remotos que
foi executada com sucesso no objecto remoto. não estão em execução, nem foram activados.
Podem ser efectuados três tipos diferentes de invocações
sobre objectos remotos: sı́ncronas, assı́ncronas, e assı́ncronas 2.1.7 Sub-tipos e herança múltipla
num só sentido (oneway). O modo sı́ncrono consiste no blo- A plataforma .NET não suporta herança de múltiplas im-
queio do cliente, após a invocação, até que alguma resposta plementações, mas suporta a herança de múltiplos inter-
ou excepção seja enviada pelo servidor ou pela plataforma. faces. Assim, um tipo de objecto pode extender uma im-
Para fazer face ao potencial fraco desempenho das chamadas plementação e implementar múltiplos interfaces.
sı́ncronas, o .NET Remoting suporta um mecanismo de in- Esta caracterı́stica permite que os objectos remotos sejam
vocações assı́ncronas, assente na utilização de delegates. Os sub-tipos da implementação MarshalByRefObject e que, ao
delegates fornecem um mecanismo de callback com verificação mesmo tempo, implementem interfaces não remotos.
de tipos, permitindo a invocação assı́ncrona de operações lo-
cais ou remotas (ver Figura 4). 2.1.8 Polimorfismo
Assim, a invocação do método é feita em dois passos: em O suporte ao polimorfismo está estaticamente restricto
primeiro lugar despoleta-se a invocação da operação remota pela herança de múltiplos interfaces. A qualquer objecto
a partir do método BeginInvoke(). Este método retorna do sistema está associado um tipo estático, sendo apenas
um objecto IAsyncResult que irá permitir obter o valor de possı́vel atribuı́r a este instâncias de objectos cujo tipo estático

3
seja um super-tipo do objecto em questão. É possı́vel então localmente no objecto remoto e o seu resultado encapsulado
redefinir determinadas operações herdadas pelos sub-tipos numa mensagem que percorre o trajecto inverso.
e determinar a execução da operação correcta através de
mecanismos de late-binding.
Esta garantia de consistência da representação dos tipos
distribuı́dos e a coerência do modelo de objectos permite in-
stituir uma noção de polimorfismo distribuı́do, abrindo por-
tas ao suporte de migração de código entre domı́nios aplica-
cionais e contextos de execução distintos.

2.2 Arquitectura
Como a maioria dos sistemas de objectos distribuı́dos, o
.NET Remoting recorre ao modelo tradicional de suporte à
invocação de operações em objectos remotos, que consiste
na implementação dessas operações numa classe, por sua
vez instanciada num processo anfitrião, em execução num
local conhecido e acessı́vel aos clientes. Como o contexto de
execução do objecto remoto está isolado em relação ao do
cliente, a invocação dos métodos remotos tem de ser efectu-
ada através de um stub ou proxy, uma cópia local do objecto
remoto que adere à sua definição de tipo. A invocação destes
métodos expostos pelo proxy resulta no envio de mensagens
serializadas através da rede. As mensagens são transferidas
pelo canal de comunicação estabelecido entre o cliente e o
servidor, sendo efectuado o processo inverso de serialização
após a sua recepção no servidor e submetido (dispatched ) o Figura 6: Entidades envolvidos na invocação de um
método para invocação no objecto remoto. O processo de método remoto.
envio do resultado da invocação é análogo, mas em sentido
contrário.
2.2.1 Referências Remotas
As referências para os objectos remotos, envolvidos no
processo descrito anteriormente, são do tipo ObjRef e contêm
toda a informação necessária para a criação dos proxys já
mencionados. A referência contém, entre outros dados, o
URI que constitui o ponto de acesso conhecido para o ob-
jecto em questão, uma série de meta-dados que descrevem o
tipo do objecto remoto, tal como o nome do assembly que
contém a sua implementação, a sua versão e chaves públicas,
entre outros. Dados acerca de todos os tipos da hierarquia
de derivação também são agrupados nesta referência e seri-
alizados de forma a serem enviados ao cliente. Ainda é in-
cluı́da informação relativa ao contexto de execução, domı́nio
Figura 5: Arquitectura das plataformas de suporte aplicacional e processo que contém o objecto associado à re-
a sistemas de objectos distribuı́dos. ferência, bem como a identificação do tipo de canal, endereço
e porta que deverão ser utilizados nos pedidos de invocação
Em particular, na infra-estrutura de Remoting, assim que remota.
um cliente activa um objecto remoto, a plataforma cria uma
instância local da classe TransparentProxy, que contém uma 2.2.2 Mensagens
lista de todas classes e métodos dos interfaces do objecto re- Na base do suporte a invocações sobre objectos remo-
moto. Assim que esta classe é criada, todas as invocações tos estão as mensagens, um tipo de objecto que abstrai o
sobre ela são interceptados pelo runtime, de forma a de- processo de invocação de métodos de uma forma orientada
terminar a sua validade e a existência de uma instância do a objectos. Assim, uma mensagem pode encapsular a in-
objecto alvo no mesmo domı́nio aplicacional em que o proxy vocação de métodos, argumentos de entrada e valores de
está em execução. Se existir, então é feito um encamin- retorno, invocações a construtores de objectos, lançamento
hamento simples para o método invocado no objecto local. de excepções, entre outros. Os objectos de mensagens im-
Caso contrário, é criado um objecto do tipo IMessage, onde plementam o tipo IMessage e são serializáveis.
são colocados os parâmetros submetidos ao método remoto
(caso existam), e encaminhada a mensagem para um ob- 2.2.3 Canais
jecto RealProxy, através do método Invoke(). Esta classe As mensagens são transmitidas entre os objectos interve-
é responsável pelo encaminhamento das mensagens para o nientes através de canais de comunicação estabelecidos na
objecto remoto, através de canais registados no servidor. altura de activação dos objectos remotos. Estes objectos
Uma vez recebida a mensagem de invocação no domı́nio são extremamente extensı́veis e permitem a construção de
aplicacional ou contexto de destino, o método é invocado mecanismos de transporte suportados por uma variedade de

4
protocolos e formatos na transmissão dos dados. No entanto, mensagens através do canal. Entre outros, poderia ser de-
a plataforma disponibiliza apenas dois canais de transporte: senvolvido um sink para a encriptação de mensagens, outro
o HttpChannel e o TcpChannel. O HttpChannel, por defeito, que guardasse um log de todas as mensagens trocadas en-
recorre ao SOAP (Simple Object Access Protocol ) para cod- tre os objectos, ou ainda outro que exigisse algum tipo de
ificar as mensagens. O SOAP é um protocolo baseado em autenticação adicional por parte dos clientes envolvidos [4].
XML, desenhado para permitir a invocação de procedimen- O desenvolvimento de novos formatters passa pela im-
tos remotos sobre HTTP, de forma a superar as restrições plementação do tipo ISerializable, que contém apenas o
impostas pelas firewalls em redes de larga escala. Em am- método GetObjectData(). Este método é chamado quando
bientes mais controlados, o TcpChannel verifica-se uma al- é necessário serializar o objecto. Quando estão envolvi-
ternativa mais eficaz, uma vez que, por defeito, utiliza um dos tipos não suportados por este método (por exemplo,
formato binário, minimizando assim o tamanho das men- referências), a plataforma recorre a surrogates e surrogate
sagens transmitidas e aumentando o desempenho da troca selectors.
de mensagens entre objectos.
Estes objectos implementam o interface IChannel e, de
modo a suportar tanto o envio como a recepção de da- 2.2.4 Activação
dos, também implementam os tipos IChannelReceiver e
A plataforma suporta a activação de objectos remotos a
IChannelSender.
partir dos cliente ou do próprio servidor. A activação por
Os canais têm a particularidade de serem constituı́dos
parte do servidor é normalmente utilizada quando os objec-
por uma série de objectos logicamente encadeados, conheci-
tos envolvidos não têm necessidade de manter o seu estado
dos por sinks, que aceitam mensagens, isto é, objectos do
entre diferentes operações, enquanto que, por outro lado, a
tipo IMessage, de um elemento anterior, efectuam alguma
activação a partir do cliente resulta numa instanciação do
operação sobre estas e submetem-nas ao próximo elemento
objecto remoto a pedido do cliente, sendo a sua gestão do
da cadeia de sinks.
tempo de vida feita através de um sistema de leases.
Assim, os objectos activados no servidor são geridos por
este, sendo instanciados apenas quando ocorre a primeira
invocação por parte de um cliente. Este tipo de objectos
apenas suporta construtores sem parâmetros e têm a sua
localização bem definida e conhecida, uma vez que estão
associados a um URI. Podem ser de dois tipos distintos:
Singleton ou SingleCall.
Os objectos do tipo Singleton baseam-se no padrão de
desenho com o mesmo nome e portanto dizem respeito a
tipos de objectos que são instanciados uma única vez e com
um único ponto global de acesso durante o seu perı́odo de
execução [3]. Tal como os restantes tipos de objectos remo-
tos, estes também têm um tempo de vida pré-determinado,
o que significa que os seus clientes não obterão necessari-
amente sempre uma referência para a mesma instância da
classe remota. Este aspecto tem implicações na gestão do
estado destes objectos e pode ser contornado, forçando a
manutenção do objecto em memória, enquanto o domı́nio
aplicacional do servidor estiver em execução, através de uma
lease nula. Assim, é possı́vel que este objecto mantenha um
determinado estado entre invocações e que este seja mod-
Figura 7: Transformações de uma mensagem através ificado ou obtido por diferentes clientes. No entanto, este
de um canal e da sua cadeia de sinks. tipo de interacção com objectos Singleton deve ser efectu-
ada com alguma precaução, uma vez que o seu acesso não
Um dos elementos mais importantes, e normalmente o é sincronizado, podendo servir dois clientes concorrentes em
primeiro nesta cadeia de objectos, é o formatter sink, re- threads de execução diferentes.
sponsável pela serialização da mensagem propriamente dita, Os tipos remotos SingleCall têm sempre uma instância
preparando-a assim para ser transmitida pelo canal. Os ele- por pedido, de modo que cada invocação por parte de um
mentos intermédios podem efectuar processamento adicional cliente é servida por uma instância diferente, com um estado
sobre esta, sendo que o último elemento da cadeia fica então distinto.
encarregado de transportar a mensagem pelo fio, de acordo Os objectos activados pelos clientes são instanciados a
com um protocolo de transporte especı́fico. partir do momento em que este cria um novo objecto do tipo
Nos canais apresentandos anteriormente, cada qual tem remoto pretendido, com o operador new ou com o método
o seu formatter apropriado. O HttpChannel utiliza um ob- Activator.CreateInstance(). Neste cenário, o cliente pode
jecto do tipo SoapFormatter, enquanto que o TcpChannel participar na gestão da vida do objecto remoto, utilizando
utiliza um BinaryFormatter. as já mencionadas leases. Também possibilita a instan-
Como já foi mencionado, todos estes componentes po- ciação parametrizada bem como a manutenção do estado
dem ser extendidos. Em particular, podem ser introduzi- do objecto por cliente, uma vez que cada cliente tem a sua
dos novos elementos na cadeia de sinks, substituı́dos ou re- instância distinta do objecto remoto em execução no servi-
movidos outros, de forma a manipular o processamento das dor.

5
2.3 Heterogeneidade 2.5 Gestão do Ciclo de Vida
A plataforma em estudo resolve de forma elegante e eficaz Nesta plataforma, a problemática relativa à gestão do ciclo
os problemas associados à heterogeneidade, normalmente de vida dos objectos é solucionada com recurso à utilização
discutidos nos sistemas de objectos distribuı́dos. de leases e sponsorships que, uma vez associadas aos objec-
tos remotos, evitam que estes sejam recolhidos pelo mecan-
2.3.1 Linguagens de Programação ismo local de recolha de lixo. A excepção a este cenário
A existência de um sistema de tipos comum, que garante reside nos objectos single-call activados no servidor, que são
a interoperabilidade e integração dos tipos, através da im- desactivados imediatamente após uma invocação sobre as
posição de regras e especificação de um modelo de objectos suas operações.
comum, resolve o problema da utilização de várias lingua-
gens de programação no processo de desenvolvimento. 2.5.1 Leases e Sponsors
Todo o código produzido por uma linguagem que esteja es- Tal como os restantes sistemas de objectos distribuı́dos,
pecificada de acordo com o Common Type System é traduzido em .NET Remoting a gestão de ciclo de vida está associada
para uma linguagem intermédia comum, que mais tarde é ao mecanismo de recolha de lixo, que mantém informação
interpretada pelo runtime e transformada em código nativo. acerca dos objectos em utilização pelos clientes. Quando
um objecto deixa de ser referenciado pelos clientes, é recol-
2.3.2 Representação dos dados hido e eventualmente destruı́do, sendo libertada a memória
Uma vez que o código nativo é executado em runtimes de- anteriormente atribuı́da.
vidamente condicionados e baseados na mesma implementação, Este processo é eficaz num cenário onde as aplicações par-
a heterogeneidade na representação dos dados não é um tilham o mesmo processo de execução (a mesma CLR). Num
problema, desde que o ambiente de execução seja comum, cenário distribuı́do, a situação é diferente, uma vez que um
isto é, tenha como base a mesma versão de uma determinada objecto pode não ter clientes locais, mas sim clientes que
implementação da CLI. estão em execução em processos e máquinas diferentes, onde
A utilização de diferentes implementações e versões de a recolha prematura de um objecto resultaria na invalidação
uma ou mais CLI’s não garante a representação homogénea da referência remota possuı́da pelos clientes.
dos dados, uma vez que a estrutura interna dos tipos pode A solução implementada na plataforma .NET envolve a
ter sido alterada, tornando-as efectivamente incompatı́veis. utilização de leases e funciona da seguinte forma: o acesso
a um objecto no servidor por parte de um cliente resulta
2.4 Localização na associação deste a um objecto lease, que mantêm, entre
A designação de serviços remotos na plataforma consiste outras propriedades, um perı́odo de tempo durante o qual
na atribuição de URIs bem conhecidos aos objectos e são o objecto servidor não deverá ser recolhido. O lease man-
definidos na fase em que estes são registados na plataforma. ager, responsável pela gestão das associações entre objectos
O registo de objectos é normalmente realizado pela aplicação e leases, dá inı́cio à contagem decrescente do tempo de lease
que os instancia, registando os canais de comunicação através a partir do momento em que a primeira referência é envi-
de operações disponibilizadas pela classe ChannelServices e ada para fora do seu domı́nio de execução. Esta entidade
os objectos remotos através da classe RemotingConfiguration. também mantém uma referência para o objecto servidor,
O registo de um objecto remoto só é possı́vel mediante a evitando assim a sua recolha para destruição. Uma vez ex-
seguinte informação: pirada a lease de um objecto, a CLR assume que não existem
clientes a utilizar referências remotas e descarta também a
1. o nome do tipo do objecto remoto. sua referência local [6].
No entanto, não são dadas garantias de que não exis-
2. o URI que o designa. tam ainda clientes que possuam referências para os objec-
3. o tipo de activação. tos remotos. É então necessário providenciar uma forma de
estes poderem extender as leases. Aqueles clientes que pre-
No caso dos objectos activados pelo servidor, esse URI é cisam de ser contactados quando o tempo de vida de um
fixo e conhecido, enquanto que nos objectos activados pe- objecto remoto termina devem recorrer a um objecto spon-
los clientes, esse URI é gerado e relativo a uma instância sor, registando-o na lease respectiva. Assim, o gestor de
particular do tipo de objecto no servidor. leases percorre a lista de sponsors associada à lease do ob-
jecto em questão e identifica se há ou não necessidade de
// registo de um canal de comunicaç~
ao extender o seu tempo de vida.
TcpChannel channel = new TcpChannel(4321);
ChannelServices.RegisterChannel(channel); 2.5.2 Propriedades das Leases
Uma lease é instanciada com valores atribuı́dos por omissão
// registo do tipo de objecto remoto às suas propriedades (ver Figura 9), mas que podem ser al-
RemotingConfiguration.RegisterWellKnownServiceType( terados antes de serem registados os objectos no servidor,
typeof(MyRemoteObject), quer programaticamente, quer através dos ficheiros de con-
"MyRemoteObjectUri", figuração da aplicação.
WellKnownObjectMode.Singleton A propriedade RenewOnCallTime tem um valor de tempo
); adicional que é automaticamente acrescentado ao tempo de
vida do objecto caso sejam invocados métodos sobre este,
perto da expiração da sua lease. Esta renovação do tempo
Figura 8: Registo tı́pico de um objecto remoto. de lease só é efectuada caso o restante tempo de vida do
objecto seja inferior ao valor atribuı́do à propriedade anteri-

6
public sealed class LifetimeServices tratamento e persistência de estruturas de dados relacionais,
{ designado por ADO.NET.
TimeSpan LeaseManagerPollTime { get; set; } Esta API em conjunto com o processo de serialização
TimeSpan InitialLeaseTime { get; set; } de objectos já abordado, poderia estar na base da imple-
TimeSpan RenewOnCallTime { get; set; } mentação de um serviço de persistência orientado para o
TimeSpan SponsorshipTimeout {get; set; } armazenamento dos objectos remotos, particularmente útil
na salvaguarda a longo-prazo do estado de execução de servi-
static LifetimeServices()
dores.
{
LeaseManagerPollTime = TimeSpan.FromSeconds(10); 2.7 Interoperabilidade
LeaseTime = TimeSpan.FromMinutes(5); A interoperabilidade da plataforma .NET Remoting em
RenewOnCallTime = TimeSpan.FromMinutes(2); relação a outros sistemas de objectos distribuı́dos assenta
SponsorshipTimeout = TimeSpan.FromMinutes(2); sobretudo no protocolo SOAP e no mecanismo de pedi-
} dos de invocações remotas facultado, expressos sob a forma
} de mensagens SOAP. Este protocolo especifica um formato
XML normalizado, que permite a inclusão de definições de
Figura 9: Classe LifetimeServices tipos e dados estruturados, independente da plataforma e
linguagem de programação utilizadas. Esta possibilidade de
oferecer serviços web, baseados em XML, a clientes poten-
ormente mencionada, evitando assim que um objecto remoto cialmente desenvolvidos sobre outras plataformas e arqui-
que seja bastante solicitado pelos seus clientes aumente pro- tecturas, garante que as mensagens podem ser trocadas e
gressivamente o seu tempo de vida. entendidas entre sistemas diferentes, escondendo assim os
A propriedade LeaseManagerPollTime indica a duração detalhes de implementação dos serviços remotos.
do intervalo de tempo que deverá decorrer entre a verificação 2.8 Configurabilidade
dos tempos das leases, que por omissão é de 10 segundos,
enquanto que a propriedade SponsorshipTimeout especifica De forma a introduzir alguma flexibilidade na configuração
o tempo que o servidor deverá esperar por respostas dos dos serviços oferecidos pelos objectos remotos, a plataforma
clientes remotos quando inquire estes acerca do estado da suporta o carregamento de determinadas propriedades a par-
sua sponsorship. Esta propriedade é importante pois é a tir de ficheiros, sem ser necessário recompilar o código.
partir deste valor que são toleradas falhas de comunicação É possı́vel então especificar num ficheiro de configuração
com os clientes, sendo estes removidos da lista de sponsors a porta e o tipo de canal utilizado no estabelecimento de
da lease caso não respondam dentro do intervalo de tempo ligações ao objecto remoto, o seu modelo de activação, o
estabelecido. URI de acesso, entre outras propriedades importantes (ver
Um objecto remoto pode também alterar as propriedades Figura 10).
do seu ciclo de vida após a sua instanciação, fornecendo uma <configuration>
implementação para o método InitializeLifetimeService <system.runtime.remoting>
e devolvendo um objecto do tipo ILease. <application name="MyServer">
<service>
2.5.3 Sponsors
<wellknown mode="Singleton"
Como foi referido anteriomente, um sponsor é utilizado type="MyServerImpl, MyServerLib"
para possibilitar um pedido de renovação do lease por parte objectUri="MyURI" />
do cliente, quando este está prestes a expirar. Este processo </service>
de renovação envolve a invocação do método Renewal no <channels>
objecto sponsor, pelo gestor de leases. <channel ref="tcp" port="8080" />
Uma vez que os objectos sponsor estão associados aos </channels>
clientes e têm de ser registados no servidor, terão de derivar </application>
da classe MarshalByRefObject e ser enviados por referência, </system.runtime.remoting>
ou então marcados como Serializable e enviados por valor. </configuration>
Na primeira hipótese, o cliente deverá garantir a manutenção
de uma referência para este objecto remoto e remover o
seu registo quando já não for necessário, ganhando nesta Figura 10: Exemplo de um ficheiro de configuração
situação a vantagem de poder controlar as suas decisões com
base em eventos ou propriedades associadas ao cliente. Por
outro lado, se o objecto sponsor for enviado por valor, é cri- 2.9 Ambientes de Execução
ada uma cópia no servidor que, apesar de ser transferida de Uma vez que os objectos remotos só podem ser activa-
forma mais eficiente , apenas poderá basear as suas decisões dos após efectuado o seu registo e o dos seus canais de
nas propriedades do servidor. comunicação, esse processo deverá ser efectuado por uma
aplicação designada para esse fim. Essa aplicação deverá
2.6 Persistência estar em execução durante todo o ciclo de vida dos objectos
O suporte ao armazenamento de tipos de objectos num registados.
repositório de dados persistente não constitui um serviço in- Em ambientes Microsoft Windows, essa aplicação pode
trinsecamente ligado ao .NET Remoting, mas está presente ser substituı́da por um serviço genérico desenvolvido com
na plataforma .NET como um componente genérico para o esse objectivo, ou então associada a um de dois serviços

7
já existentes: o IIS (Internet Information Services) ou aos a interoperabilidade entre objectos desenvolvidos em difer-
serviços COM+. entes linguagens, possibilitando a execução e comunicação
entre estes num ambiente CLI, onde o tratamento de erros
2.9.1 Integração no IIS estabelecido segue um modelo at-most-once.
O IIS é um servidor web e normalmente está sempre em A utilização de proxys como mecanismo de atingir um
execução num ambiente Windows. Como tal, presta-se a ser modelo de transparência de acesso é comum a todos os sis-
um bom anfitrião aos componentes remotos que se querem temas referidos, sendo de realçar que em Remoting, a criação
disponibilizar, apesar de estar limitado à utilização de canais e manipulação dos objectos deste tipo é completamente in-
HttpChannel. Por outro lado, possibilita uma configuração visı́vel para o utilizador ou programador.
rápida das restrições de segurança impostas aos componentes O mecanismo de leases constitui o modelo de recolha de
e a alteração da sua configuração sem ser necessário re- objectos para os quais já não existem referências e estão
iniciar o serviço. também implementadas variadas formas de suporte à ac-
tivação dinâmica dos objectos servidores.
2.9.2 Integração nos serviços COM+ Em suma, a infra-estrutura de Remoting tem bastantas
Outra opção passa por tirar partido das funcionalidades semelhanças com a do Java/RMI, mas oferece de raiz, em
oferecidas pelo ambiente COM+, tais como o suporte a determinados aspectos, mais funcionalidades associadas ao
transacções distribuı́das, segurança baseada em roles, e pool- tratamento dos objectos remotos, e na configuração e ex-
ing de objectos. Um componente remoto pode participar tensão dos canais de comunicação. A interoperabilidade com
do contexto de execução dos serviços COM+ derivando da outras plataformas através de protocolos como o SOAP e
classe ServicedComponent. Esta classe, e o espaço de nomes HTTP evidencia também uma abertura para a integração
System.EnterpriseServices, possibilita a utilização de atrib- entre sistemas com diferentes implementações.
utos particulares ao COM+ num objecto em execução na
CLR e a todos os benefı́cios que daı́ resultam. 5. REFERÊNCIAS
[1] W. Emmerich. Engineering Distributed Objects. John
3. EXEMPLOS Wiley and Sons, Ltd, 2000.
Procedeu-se ao desenvolvimento de um conjunto de exem- [2] B. et al. Network Objects. DIGITAL, Inc., 1995.
plos simples, demonstrativos das funcionalidades disponibi- [3] G. et al. Design Patterns: Elements of Reusable
lizadas pelo infra-estrutura de Remoting, sobre uma imple- Object-Oriented Software. Addison-Wesley, 1995.
mentação da CLI open source e compatı́vel com sistemas [4] M. et al. Microsoft .NET Remoting. Microsoft Press,
UNIX, designada por Mono e disponı́vel em http://www.mono- 2003.
project.com/. [5] E. International. Standard ECMA-335: Common
Esta distribuição implementa toda a funcionalidade da Language Infrastructure. ECMA International, 2005.
versão 1.1 da plataforma .NET disponı́vel para sistemas op- [6] J. Lowy. Managing the lifetime of remote .net objects
erativos Microsoft Windows e ainda extende a distribuição with leasing and sponsorhip. MSDN Magazine,
base com uma série de módulos adicionais. É composta Dezembro 2003.
por uma máquina virtual, que constitui o ambiente con- [7] SUN. Java RMI Specification. Sun Microsystems, Inc.,
trolado de execução das aplicações, um compilador just-in- 1998.
time, para a linguagem intermédia, uma API que reproduz
as Framework Class Libraries da Microsoft e um compilador
de C#. APÊNDICES
São apresentadas, no apêndice deste documento, listagens
de alguns dos exemplos desenvolvidos, sendo que os restantes
A. LISTAGENS
estarão disponı́veis num ficheiro que deverá acompanhar este Apresentamos em seguida implementações de alguns ex-
trabalho. emplos desenvolvidos no âmbito de uma demonstração das
capacidades da plataforma .NET Remoting, conforme de-
talhadas no texto.
4. CONCLUSÕES
A infra-estrutura de Remoting, integrada na plataforma A.1 Hello World - Client Activated
.NET, apresenta caracterı́sticas comuns a outros sistemas de
objectos distribuı́dos, não alheio ao facto de esta ter sido a A.1.1 RemoteObject.cs
abordagem mais recente ao suporte de invocações em objec-
tos remotos e toda a problemática em redor. using System;
Tal como o CORBA, DCOM e Java/RMI, em Remoting using System.Runtime.Remoting;
é possı́vel solicitar a execução de operações em objectos res-
identes noutros contextos de execução, num ambiente dis- namespace com.mgcm.net.remoting
tribuı́do. À semelhança do Java/RMI, a inclusão no modelo {
de objectos de objectos não-remotos exige uma diferenciação public class RemoteObject : MarshalByRefObject
no seu tratamento a nı́vel de tipos, e, como nos sistemas {
acima mencionados, todo o objecto remoto é identificado a public RemoteObject()
partir de uma referência que assegura a transparência de {
localização. }
A Common Type System estabelece a separação entre a
noção de interfaces e implementações, e define regras para public string HelloWorld()

8
{ using System;
return "Hello World!"; using System.Runtime.Remoting;
} using System.Runtime.Remoting.Channels;
} using System.Runtime.Remoting.Channels.Tcp;
}
namespace com.mgcm.net.remoting
A.1.2 RemoteServer.cs {
public class RemoteClient
using System; {
using System.Runtime.Remoting; public static int Main(string[] args)
using System.Runtime.Remoting.Channels; {
using System.Runtime.Remoting.Channels.Tcp; TcpChannel tcp = new TcpChannel();
ChannelServices.RegisterChannel(tcp);
namespace com.mgcm.net.remoting
{ RemoteObject obj = (RemoteObject)
public class RemoteServer Activator.GetObject(
{ typeof(com.mgcm.net.remoting.RemoteObject),
public static int Main(string[] args) "tcp://localhost:8080/HelloWorld");
{
TcpChannel tcp = new TcpChannel(8080); Console.WriteLine(obj.HelloWorld());
ChannelServices.RegisterChannel(tcp); return 0;
}
RemotingConfiguration.RegisterWellKnownServiceType( }
typeof(RemoteObject), }
"HelloWorld",
WellKnownObjectMode.SingleCall); A.3 Execução de Código Móvel

System.Console.WriteLine("server running..."); A.3.1 Interfaces.cs


System.Console.ReadLine();
return 0; namespace com.mgcm.net.remoting
} {
} public interface ITask
} {
void exec();
A.1.3 RemoteClient.cs }

public interface IAgent


using System;
{
using System.Runtime.Remoting;
void run();
using System.Runtime.Remoting.Channels;
}
using System.Runtime.Remoting.Channels.Tcp;
public interface IAgentHost
namespace com.mgcm.net.remoting
{
{
void accept(IAgent agent);
public class RemoteClient
}
{
}
public static int Main(string[] args)
{ A.3.2 Tasks.cs
TcpChannel tcp = new TcpChannel();
ChannelServices.RegisterChannel(tcp); using System;

RemoteObject obj = (RemoteObject) namespace com.mgcm.net.remoting


Activator.CreateInstance( {
typeof(com.mgcm.net.remoting.RemoteObject)); [Serializable]
public class TaskHello: ITask
Console.WriteLine(obj.HelloWorld()); {
return 0; public TaskHello():base()
} {
} }
}
public void exec()
A.2 Hello World - Server Activated {
System.Console.WriteLine("Hello World");
A.2.1 RemoteClient.cs }

9
} A.3.4 Agent.cs
[Serializable] using System;
public class TaskDateNow: ITask
{ namespace com.mgcm.net.remoting
public TaskDateNow():base() {
{ [Serializable]
} public class Agent: IAgent
{
public void exec() private ITask task;
{
System.Console.WriteLine(DateTime.Now); public Agent(ITask task)
} {
} this.task = task;
} }
A.3.3 AgentHost.cs public void run()
using System; {
using System.Runtime.Remoting; task.exec();
using System.Runtime.Remoting.Channels; }
using System.Runtime.Remoting.Channels.Tcp; }
using System.Collections; }
using System.Threading; A.3.5 Server.cs
namespace com.mgcm.net.remoting using System;
{ using System.Runtime.Remoting;
public class AgentHost: MarshalByRefObject, using System.Runtime.Remoting.Channels;
IAgentHost using System.Runtime.Remoting.Channels.Tcp;
{
private Stack agents; namespace com.mgcm.net.remoting
{
public AgentHost() public class Server
{ {
agents = new Stack(); public static void Main(string[] args)
{
Thread t = new Thread( int port = 8080;
new ThreadStart(execAgents) TcpChannel channel = new TcpChannel(port)
); ChannelServices.RegisterChannel(channel);
t.Start();
} RemotingConfiguration.RegisterWellKnownServiceType(
typeof(AgentHost),
public void accept(IAgent agent) "AgentHost",
{ WellKnownObjectMode.Singleton
agents.Push(agent); );
}
System.Console.ReadLine();
public void execAgents() }
{ }
while (true) }
{
if (agents.Count > 0) A.3.6 Client.cs
{
IAgent agent = (IAgent) agents.Pop(); using System;
Thread t = new Thread( using System.Runtime.Remoting;
new ThreadStart(agent.run) using System.Runtime.Remoting.Channels;
); using System.Runtime.Remoting.Channels.Tcp;
t.Start();
} namespace com.mgcm.net.remoting
System.Threading.Thread.Sleep(500); {
} public class Client
} {
} public static void Main(string[] args)
} {

10
TcpChannel channel = new TcpChannel();
ChannelServices.RegisterChannel(channel);

IAgentHost host = (IAgentHost)


Activator.GetObject(
typeof(com.mgcm.net.remoting.IAgentHost),
"tcp://localhost:8080/AgentHost"
);

ITask task1 = new TaskHello();


ITask task2 = new TaskDateNow();
IAgent agent1 = new Agent(task1);
IAgent agent2 = new Agent(task2);

host.accept(agent1);
host.accept(agent2);
}
}
}

11