Você está na página 1de 11

.NET Remoting

Um estudo ao suporte de invocac¸ oes˜ em objectos remotos na plataforma .NET

Milton Moura

Faculdade de Cienciasˆ

e Tecnologia

Universidade Nova de Lisboa

Pos-Graduac´

¸ ao˜ em Eng a Informatica´

miltonmoura@gmail.com

RESUMO

Existe hoje em dia um n´umero consider´avel de tecnologias orientadas para a programa¸c˜ao de sistemas de objectos dis- tribu´ıdos, como s˜ao exemplo disso o CORBA, o Java/RMI, o DCOM e, mais recentemente, o .NET Remoting. Qualquer uma delas oferece um agregado de servi¸cos e funcionalidades que diferem na sua abordagem e implementa¸c˜ao, tornando- as mais ou menos complexas e apropriadas para determina- dos cen´arios de utiliza¸c˜ao. Este trabalho resulta de uma an´alise ao suporte de in- voca¸c˜oes em objectos remotos na plataforma de desenvolvi- mento .NET, tendo como ambiente de execu¸c˜ao a imple- menta¸c˜ao multi-plataforma da especifica¸c˜ao CLI denomi-

nada Mono, e pretende expor os v´arios aspectos dos servi¸cos disponbilizados pelo componente .NET Remoting, bem como

a sua arquitectura e funcionamento interno. Numa vertente pr´actica, s˜ao apresentados alguns exemp- los de diferentes t´ecnicas normalmente utilizadas em ambi- entes de sistemas de objectos distribu´ıdos, com o objectivo de oferecer assim uma vis˜ao comparativa deste suporte em rela¸c˜ao a outros j´a estudados.

˜

1. INTRODUC¸ AO

As tecnologias de suporte aos sistemas distribu´ıdos de ob- jectos permitem que componentes em execu¸c˜ao numa de-

termina m´aquina sejam acedidos por aplica¸c˜oes ou objectos em execu¸c˜ao noutras m´aquinas distintas. Tecnologias como

o CORBA, o Java/RMI, o DCOM e o .NET Remoting s˜ao

exemplos de sistemas deste tipo e, apesar de estarem imple-

mentados de forma muito diferente e com funcionalidades distintas, mantˆem algumas semelhan¸cas:

Os objectos tˆem uma identidade unica´ e podem ter um estado de execu¸c˜ao.

A utiliza¸c˜ao de objectos remotos tem a mesma sem˜antica dos objectos locais.

Est˜ao associados a um modelo de componentes, onde os detalhes de implementa¸c˜ao est˜ao escondidos.

Tˆem modelos de tolerˆancia a falhas bem definidos.

A implementa¸c˜ao de suporte `a invoca¸c˜ao de objectos re- motos no .NET Remoting ´e semelhante `a do Java/RMI [7] em muitos aspectos, pois ambos tˆem como base a especi- fica¸c˜ao de Birrel et al [2] para RPC’s (Remote Procedure Calls), que introduziu os conceitos b´asicos utilizados nas

1

Ricardo Seabra

Faculdade de Cienciasˆ

e Tecnologia

Universidade Nova de Lisboa Licenciatura em Eng a Informatica´

ricardo.seabra@gmail.com

infra-estruturas deste tipo, como os stubs, o processo de marshaling e a IDL [1].

A restante plataforma .NET ´e constitu´ıda por um ambi-

ente controlado de execu¸c˜ao de c´odigo, designado por CLR (Common Language Runtime), um gestor de mem´oria, re- spons´avel pela recolha autom´atica de referˆencias n˜ao uti- lizadas, um sistema de tipos unificado (Common Type Sys- tem) que permite a interoperabilidade entre objectos imple- mentados em diferentes linguagens de programa¸c˜ao, compi- ladas por uma ferramenta que implemente a CLS (Common Language Specification), e um conjunto de APIs, separados em m´odulos l´ogicos, que enriquece o modelo de objectos base fornecido [5].

2. .NET REMOTING

Integrado na especifica¸c˜ao da plataforma Microsoft .NET, o componente .NET Remoting permite o desenvolvimento de aplica¸c˜oes distribu´ıdas, onde os objectos participantes podem ser executados em m´aquinas e processos diferentes e em dominios aplicacionais distintos. Na g´enese do .NET Remoting est´a uma implementa¸c˜ao abstracta de comunica¸c˜ao entre processos que separa os ob- jectos remotos e seus potenciais clientes do mecanismo de comunica¸c˜ao entre si, tornando-se assim uma plataforma

flex´ıvel e extens´ıvel, onde os protocolos de comunica¸c˜ao e

 

´

formatos de serializa¸c˜ao podem ser facilmente alterados.

E

tamb´em agn´ostica ao modelo da aplica¸c˜ao, possibilitando a

interoperabilidade entre aplica¸c˜oes Web, servi¸cos de sistema ou programas executados na consola.

A plataforma disponibiliza ainda um conjunto de servi¸cos

comuns em ambientes de middleware, como o suporte `a ac- tiva¸c˜ao de objectos remotos, gest˜ao do seu ciclo de vida e seguran¸ca nos canais de mensagens.

2.1 Meta-Modelo de Objectos e Definic¸ ao˜ de Interfaces

O c´odigo executado na plataforma .NET tem v´arios n´ıveis

de isolamento, sendo que num processo da CLR podem estar em execu¸c˜ao v´arios dom´ınios aplicacionais. Em qualquer dom´ınio aplicacional s˜ao dadas as seguintes garantias:

1. Uma aplica¸c˜ao pode ser parada de forma indepen- dente.

2. Uma aplica¸c˜ao n˜ao pode aceder directamente a c´odigo e recursos de outra aplica¸c˜ao.

3. Uma falha na aplica¸c˜ao n˜ao afecta as restantes aplica¸c˜oes.

4.

A

configura¸c˜ao da aplica¸c˜ao determina o local de onde

o

c´odigo ´e carregado e a sua vers˜ao.

Um dom´ınio aplicacional pode ainda ser dividido em con- textos, que asseguram uma s´erie de restri¸c˜oes e semˆantica de seguran¸ca no acesso aos objectos que neles se encontrem em execu¸c˜ao. Por omiss˜ao, todo o dom´ınio aplicacional cont´em pelo menos um contexto, onde s˜ao criados todos os objec- tos, excepto aqueles que necessitam de um novo contexto especializado.

aqueles que necessitam de um novo contexto especializado. Figura 1: N´ıveis de isolamento da CLR. 2.1.1

Figura 1: N´ıveis de isolamento da CLR.

2.1.1 Objectos

O .NET Remoting possbilita a invoca¸c˜ao de m´etodos so-

´

E in-

diferente ao sistema a linguagem em que est˜ao implementa- dos os objectos servidores e objectos clientes, podendo esta

ser distinta. O sistema unificado de tipos da plataforma gere a representa¸c˜ao interna dos objectos e garante assim a sua interoperabilidade.

A invoca¸c˜ao remota de m´etodos depende da obten¸c˜ao de

uma referˆencia para o objecto remoto, referˆencia esta que cont´em uma s´erie de meta-dados necess´arios para que o

cliente efectue a invoca¸c˜ao de forma transparente, utilizando uma semˆantica de acesso idˆentica `a dos objectos locais.

A obten¸c˜ao dessa referˆencia ´e levado a cabo atrav´es de um

canal de comunica¸c˜oes estabelecido com o servidor, desig- nado por um URI (Universal Resource Identifier ) de acesso unico.´ Ao iniciar, ´e da responsabilidade do servidor registar ambos estas propriedades na plataforma.

bre objectos remotos, em execu¸c˜ao num CLR host.

2.1.2 Tipos

Com o objectivo de possibilitar a interac¸c˜ao entre objectos residentes em diferentes n´ıveis de isolamento da plataforma, os tipos de objectos objectos podem ser classificados de re- motos ou n˜ao-remotos. Um tipo ´e considerado remoto se:

1. As suas instˆancias podem atravessar os n´ıveis de iso- lamento da plataforma.

2. Outros objectos podem aceder a instˆancias do tipo, atravessando os n´ıveis de isolamento da plataforma.

Qualquer tipo de objecto que n˜ao satisfa¸ca estas pro- priedades, ´e n˜ao-remoto.

Os tipos de objectos remotos podem ser classificados de acordo com trˆes categorias: marshal-by-value, marshal-by- reference ou context-bound. As instˆancias dos tipos marshal- by-value podem ser enviadas entre dom´ınios aplicacionais atrav´es de um processo de serializa¸c˜ao, que corresponde `a codifica¸c˜ao do estado actual de um objecto numa sequˆencia de bits. A recep¸c˜ao de um objecto deste tipo resulta na cria¸c˜ao de uma c´opia no destino, com o mesmo estado do objecto original. Os objectos deste tipo s˜ao caracteriza- dos por um atributo especificado na sua defini¸c˜ao, o atrib- uto Serializable. No entanto, ´e poss´ıvel que um objecto definido com este atributo contenha propriedades que n˜ao 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˜ao utilizados quando se pretende manter uma unica´ instˆancia desse tipo acess´ıvel num determinado dom´ınio aplicacional, sendo pas- sada uma referˆencia dessa instˆancia aos seus clientes, em vez de uma c´opia serializada. Assim, para que os objec- tos possam ser acedidos remotamente, estes tˆem de derivar do tipo MarshalByRefObject (ver Figura 2), de forma a su- portar essa funcionalidade. As referˆencias envolvidas neste processo s˜ao objectos do tipo ObjRef.

[Serializable]

public

abstract

class

MarshalByRefObject

 

{

protected

MarshalByRefObject

()

{

}

internal

Identity

GetObjectIdentity

(

 

MarshalByRefObject

obj,

 

out

bool

IsClient

);

[NonSerialized]

 

internal

ServerIdentity

ObjectIdentity

 
 

{

get;

set;

}

public

virtual

ObjRef

CreateObjRef

 

(Type

type);

public

virtual

object

GetLifetimeService

();

public

virtual

object

InitializeLifetimeService

();

}

Figura 2: Excerto da classe MarshalByRefObject

Por ultimo,´ os tipos context-bound constituem uma espe- cializa¸c˜ao do objecto remoto t´ıpico, passado por referˆencia, que neste caso est´a restrito ao contexto de execu¸c˜ao em que ´e instanciado. Isto significa que o seu acesso, inclusive a par- tir do mesmo dom´ınio aplicacional, envolve sempre o envio de uma referˆencia remota para os objectos clientes, em vez da invoca¸c˜ao local normal que seria de esperar em situa¸c˜oes deste tipo. Essa funcionalidade ´e adquirida derivando do tipo ContextBoundObject. Os restantes tipos n˜ao-remotos definidos para a plataforma .NET s˜ao suportados pela API de Remoting de forma trans- parente, possibilitando a utiliza¸c˜ao de qualquer classe, in- terface, enumera¸c˜ao e objecto, sem quaisquer limita¸c˜oes. Partindo do princ´ıpio que tanto os clientes como os ob- jectos servidor est˜ao contidos em plataformas de execu¸c˜ao idˆenticas, isto ´e, em CLRs baseadas numa mesma vers˜ao de implementa¸c˜ao, a interoperabilidade a n´ıvel de tipos de dados est´a solucionada `a partida.

2

2.1.3 Atributos

Um tipo de objecto remoto pode definir atributos, desig- nados por propriedades na plataforma .NET, e especificar se estes s˜ao s´o de leitura ou de leitura e escrita. No entanto, a sua implementa¸c˜ao interna, forma de acesso e representa¸c˜ao s˜ao em tudo idˆenticas aos dos m´etodos.

interface

IRemoteObject

 

{

 

int

MyRemoteMethod();

 

//

propriedade

s´o

de

leitura

 

double

MyFloatProperty

{

get;

}

//

propriedade

de

leitura-escrita

int

MyIntProperty

{

get;

set;

}

}

Figura 3: Exemplo de defini¸c˜ao de propriedades

2.1.4 Operac¸ oes˜

Designados por m´etodos, as opera¸c˜oes em Remoting po- dem ser invocadas desde que declaradas como p´ublicas na

implementa¸c˜ao do tipo de objecto remoto. Caso o objecto remoto seja uma implementa¸c˜ao de um ou mais interfaces, ent˜ao todos os m´etodos implementados, necess´arios para satisfazer o contrato, s˜ao p´ublicos.

A semˆantica de invoca¸c˜ao das opera¸c˜oes remotas ´e muito

delegate

string

string

MyDelegate(int

myValue);

myValue);

DoSomething(int

MyDelegate

md

=

new

MyDelegate(DoSomething);

//

IAsyncResult

invoca¸c~ao

ass´ıncrona

ar

=

md.BeginInvoke(

someValue,

null,

null);

//

string

obten¸c~ao

do

result

=

resultado

md.EndInvoke(ar);

Figura 4: Exemplo de invoca¸c˜ao ass´ıncrona

´

retorno da fun¸c˜ao.

voca¸c˜ao ass´ıncrona num s´o sentido, ou seja, os m´etodos n˜ao

podem possuir retorno ou parˆametros de sa´ıda. Apesar de existir uma API de reflex˜ao na especifica¸c˜ao

da CLI (System.Reflection), esta n˜ao est´a integrada com

o Remoting de forma a possibilitar a invoca¸c˜ao dinˆamica

de opera¸c˜oes. Est´a portanto limitada `a invoca¸c˜ao est´atica

e dependente do acesso `a defini¸c˜ao dos tipos dos objectos num assembly local ou registado na GAC (Global Assembly Cache).

E tamb´em suportado um modo de in-

2.1.6 Tratamento de erros

O tratamento de erros, `a semelhan¸ca do que acontece

semelhante `a dos m´etodos locais, uma vez que os parˆametros podem ser passados por referˆencia ou por valor. A pas- sagem de um parˆametro por referˆencia significa que ´e pas- sado um apontador com a informa¸c˜ao necess´aria para que

na restante plataforma, ´e efectuada atrav´es da propaga¸c˜ao de excep¸c˜oes, objectos do tipo Exception que dever˜ao ser definidos como serializ´aveis, de forma a poderem ser trans- formadas e enviados pelos canais de comunica¸c˜ao definidos

´

a

opera¸c˜ao o manipule, tal como a sua localiza¸c˜ao e outros

entre os objectos remotos e clientes envolvidos. Em partic-

dados necess´arios. A passagem de objectos por valor resulta na cria¸c˜ao de uma c´opia no contexto de execu¸c˜ao do m´etodo invocado, idˆentica `a do objecto submetido. No entanto, quando est˜ao envolvidos objectos remotos, a sua passagem como parˆametro de um m´etodo remoto de-

ular, os erros com origem na infra-estrutura de Remoting, lan¸cam apenas um tipo de excep¸c˜ao: o RemotingException. Uma excep¸c˜ao deste tipo pode ser levantada por in´umeras raz˜oes, entre as quais:

pende do seu tipo, mais precisamente, se este ´e marshal-by-

instanciado um tipo de objecto remoto que n˜ao deriva

E

reference ou marshal-by-value.

de MarshalByRefObject.

2.1.5 Invocac¸ oes˜

A semˆantica de invoca¸c˜oes nesta plataforma ´e do tipo at-

most-once, o que significa que a recep¸c˜ao de uma excep¸c˜ao resultante de uma invoca¸c˜ao remota indica que o m´etodo alvo poder´a n˜ao ter sido executado. Por outro lado, a inex- istˆencia de erros constitui uma garantia de que a opera¸c˜ao foi executada com sucesso no objecto remoto. Podem ser efectuados trˆes tipos diferentes de invoca¸c˜oes sobre objectos remotos: s´ıncronas, ass´ıncronas, e ass´ıncronas num s´o sentido (oneway). O modo s´ıncrono consiste no blo- queio do cliente, ap´os a invoca¸c˜ao, at´e que alguma resposta ou excep¸c˜ao seja enviada pelo servidor ou pela plataforma. Para fazer face ao potencial fraco desempenho das chamadas s´ıncronas, o .NET Remoting suporta um mecanismo de in-

voca¸c˜oes ass´ıncronas, assente na utiliza¸c˜ao de delegates. Os delegates fornecem um mecanismo de callback com verifica¸c˜ao de tipos, permitindo a invoca¸c˜ao ass´ıncrona de opera¸c˜oes lo- cais ou remotas (ver Figura 4). Assim, a invoca¸c˜ao do m´etodo ´e feita em dois passos: em primeiro lugar despoleta-se a invoca¸c˜ao da opera¸c˜ao remota

a partir do m´etodo BeginInvoke(). Este m´etodo retorna

um objecto IAsyncResult que ir´a permitir obter o valor de

3

Especifica¸c˜ao inv´alida do ponto de acesso de um tipo de objecto remoto, isto ´e, o URI est´a mal formado.

Protocolos de comunica¸c˜ao diferentes entre os clientes

e os objectos servidor.

A invoca¸c˜ao de opera¸c˜oes sobre objectos remotos que n˜ao est˜ao em execu¸c˜ao, nem foram activados.

2.1.7 Sub-tipos e heranc¸a multipla´

A plataforma .NET n˜ao suporta heran¸ca de m´ultiplas im- plementa¸c˜oes, mas suporta a heran¸ca de m´ultiplos inter- faces. Assim, um tipo de objecto pode extender uma im- plementa¸c˜ao e implementar m´ultiplos interfaces. Esta caracter´ıstica permite que os objectos remotos sejam sub-tipos da implementa¸c˜ao MarshalByRefObject e que, ao mesmo tempo, implementem interfaces n˜ao remotos.

2.1.8 Polimorfismo

O suporte ao polimorfismo est´a estaticamente restricto

pela heran¸ca de m´ultiplos interfaces. A qualquer objecto do sistema est´a associado um tipo est´atico, sendo apenas poss´ıvel atribu´ır a este instˆancias de objectos cujo tipo est´atico

´

seja um super-tipo do objecto em quest˜ao.

redefinir determinadas opera¸c˜oes herdadas pelos sub-tipos

e determinar a execu¸c˜ao da opera¸c˜ao correcta atrav´es de

mecanismos de late-binding. Esta garantia de consistˆencia da representa¸c˜ao dos tipos distribu´ıdos e a coerˆencia do modelo de objectos permite in- stituir uma no¸c˜ao de polimorfismo distribu´ıdo, abrindo por- tas ao suporte de migra¸c˜ao de c´odigo entre dom´ınios aplica- cionais e contextos de execu¸c˜ao distintos.

E poss´ıvel ent˜ao

2.2 Arquitectura

Como a maioria dos sistemas de objectos distribu´ıdos, o .NET Remoting recorre ao modelo tradicional de suporte `a invoca¸c˜ao de opera¸c˜oes em objectos remotos, que consiste na implementa¸c˜ao dessas opera¸c˜oes numa classe, por sua vez instanciada num processo anfitri˜ao, em execu¸c˜ao num local conhecido e acess´ıvel aos clientes. Como o contexto de execu¸c˜ao do objecto remoto est´a isolado em rela¸c˜ao ao do cliente, a invoca¸c˜ao dos m´etodos remotos tem de ser efectu- ada atrav´es de um stub ou proxy, uma c´opia local do objecto remoto que adere `a sua defini¸c˜ao de tipo. A invoca¸c˜ao destes m´etodos expostos pelo proxy resulta no envio de mensagens serializadas atrav´es da rede. As mensagens s˜ao transferidas pelo canal de comunica¸c˜ao estabelecido entre o cliente e o servidor, sendo efectuado o processo inverso de serializa¸c˜ao ap´os a sua recep¸c˜ao no servidor e submetido (dispatched ) o m´etodo para invoca¸c˜ao no objecto remoto. O processo de envio do resultado da invoca¸c˜ao ´e an´alogo, mas em sentido contr´ario.

da invoca¸c˜ao ´e an´alogo, mas em sentido contr´ario. Figura 5: Arquitectura das plataformas de suporte a

Figura 5: Arquitectura das plataformas de suporte a sistemas de objectos distribu´ıdos.

Em particular, na infra-estrutura de Remoting, assim que um cliente activa um objecto remoto, a plataforma cria uma instˆancia local da classe TransparentProxy, que cont´em uma

lista de todas classes e m´etodos dos interfaces do objecto re- moto. Assim que esta classe ´e criada, todas as invoca¸c˜oes sobre ela s˜ao interceptados pelo runtime, de forma a de- terminar a sua validade e a existˆencia de uma instˆancia do objecto alvo no mesmo dom´ınio aplicacional em que o proxy est´a em execu¸c˜ao. Se existir, ent˜ao ´e feito um encamin- hamento simples para o m´etodo invocado no objecto local. Caso contr´ario, ´e criado um objecto do tipo IMessage, onde s˜ao colocados os parˆametros submetidos ao m´etodo remoto (caso existam), e encaminhada a mensagem para um ob- jecto RealProxy, atrav´es do m´etodo Invoke(). Esta classe

´e respons´avel pelo encaminhamento das mensagens para o

objecto remoto, atrav´es de canais registados no servidor. Uma vez recebida a mensagem de invoca¸c˜ao no dom´ınio aplicacional ou contexto de destino, o m´etodo ´e invocado

4

localmente no objecto remoto e o seu resultado encapsulado numa mensagem que percorre o trajecto inverso.

encapsulado numa mensagem que percorre o trajecto inverso. Figura 6: Entidades envolvidos na invoca¸c˜ao de um

Figura 6: Entidades envolvidos na invoca¸c˜ao de um m´etodo remoto.

2.2.1 Referenciasˆ

Remotas

As referˆencias para os objectos remotos, envolvidos no processo descrito anteriormente, s˜ao do tipo ObjRef e contˆem toda a informa¸c˜ao necess´aria para a cria¸c˜ao dos proxys j´a mencionados. A referˆencia cont´em, entre outros dados, o URI que constitui o ponto de acesso conhecido para o ob- jecto em quest˜ao, uma s´erie de meta-dados que descrevem o tipo do objecto remoto, tal como o nome do assembly que cont´em a sua implementa¸c˜ao, a sua vers˜ao e chaves p´ublicas, entre outros. Dados acerca de todos os tipos da hierarquia de deriva¸c˜ao tamb´em s˜ao agrupados nesta referˆencia e seri- alizados de forma a serem enviados ao cliente. Ainda ´e in-

clu´ıda informa¸c˜ao relativa ao contexto de execu¸c˜ao, dom´ınio aplicacional e processo que cont´em o objecto associado `a re- ferˆencia, bem como a identifica¸c˜ao do tipo de canal, endere¸co

e porta que dever˜ao ser utilizados nos pedidos de invoca¸c˜ao remota.

2.2.2 Mensagens

Na base do suporte a invoca¸c˜oes sobre objectos remo-

tos est˜ao as mensagens, um tipo de objecto que abstrai o processo de invoca¸c˜ao de m´etodos de uma forma orientada

a objectos. Assim, uma mensagem pode encapsular a in-

voca¸c˜ao de m´etodos, argumentos de entrada e valores de retorno, invoca¸c˜oes a construtores de objectos, lan¸camento de excep¸c˜oes, entre outros. Os objectos de mensagens im- plementam o tipo IMessage e s˜ao serializ´aveis.

2.2.3 Canais

As mensagens s˜ao transmitidas entre os objectos interve- nientes atrav´es de canais de comunica¸c˜ao estabelecidos na altura de activa¸c˜ao dos objectos remotos. Estes objectos s˜ao extremamente extens´ıveis e permitem a constru¸c˜ao de mecanismos de transporte suportados por uma variedade de

protocolos e formatos na transmiss˜ao dos dados. No entanto,

a

plataforma disponibiliza apenas dois canais de transporte:

o

HttpChannel e o TcpChannel. O HttpChannel, por defeito,

recorre ao SOAP (Simple Object Access Protocol ) para cod- ificar as mensagens. O SOAP ´e um protocolo baseado em XML, desenhado para permitir a invoca¸c˜ao de procedimen- tos remotos sobre HTTP, de forma a superar as restri¸c˜oes impostas pelas firewalls em redes de larga escala. Em am- bientes mais controlados, o TcpChannel verifica-se uma al- ternativa mais eficaz, uma vez que, por defeito, utiliza um formato bin´ario, minimizando assim o tamanho das men- sagens transmitidas e aumentando o desempenho da troca de mensagens entre objectos. Estes objectos implementam o interface IChannel e, de modo a suportar tanto o envio como a recep¸c˜ao de da- dos, tamb´em implementam os tipos IChannelReceiver e IChannelSender. Os canais tˆem a particularidade de serem constitu´ıdos por uma s´erie de objectos logicamente encadeados, conheci- dos por sinks, que aceitam mensagens, isto ´e, objectos do tipo IMessage, de um elemento anterior, efectuam alguma opera¸c˜ao sobre estas e submetem-nas ao pr´oximo elemento da cadeia de sinks.

e submetem-nas ao pr´oximo elemento da cadeia de sinks . Figura 7: Transforma¸c˜oes de uma mensagem

Figura 7: Transforma¸c˜oes de uma mensagem atrav´es de um canal e da sua cadeia de sinks.

Um dos elementos mais importantes, e normalmente o primeiro nesta cadeia de objectos, ´e o formatter sink, re- spons´avel pela serializa¸c˜ao da mensagem propriamente dita, preparando-a assim para ser transmitida pelo canal. Os ele- mentos interm´edios podem efectuar processamento adicional sobre esta, sendo que o ultimo´ elemento da cadeia fica ent˜ao encarregado de transportar a mensagem pelo fio, de acordo com um protocolo de transporte espec´ıfico. Nos canais apresentandos anteriormente, cada qual tem

o seu formatter apropriado. O HttpChannel utiliza um ob- jecto do tipo SoapFormatter, enquanto que o TcpChannel utiliza um BinaryFormatter. Como j´a foi mencionado, todos estes componentes po- dem ser extendidos. Em particular, podem ser introduzi- dos novos elementos na cadeia de sinks, substitu´ıdos ou re- movidos outros, de forma a manipular o processamento das

5

mensagens atrav´es do canal. Entre outros, poderia ser de- senvolvido um sink para a encripta¸c˜ao de mensagens, outro que guardasse um log de todas as mensagens trocadas en- tre os objectos, ou ainda outro que exigisse algum tipo de

autentica¸c˜ao adicional por parte dos clientes envolvidos [4].

O desenvolvimento de novos formatters passa pela im-

plementa¸c˜ao do tipo ISerializable, que cont´em apenas o m´etodo GetObjectData(). Este m´etodo ´e chamado quando

´e necess´ario serializar o objecto. Quando est˜ao envolvi-

dos tipos n˜ao suportados por este m´etodo (por exemplo, referˆencias), a plataforma recorre a surrogates e surrogate selectors.

2.2.4 Activac¸ ao˜

A plataforma suporta a activa¸c˜ao de objectos remotos a

partir dos cliente ou do pr´oprio servidor. A activa¸c˜ao por parte do servidor ´e normalmente utilizada quando os objec- tos envolvidos n˜ao tˆem necessidade de manter o seu estado entre diferentes opera¸c˜oes, enquanto que, por outro lado, a

activa¸c˜ao a partir do cliente resulta numa instancia¸c˜ao do objecto remoto a pedido do cliente, sendo a sua gest˜ao do tempo de vida feita atrav´es de um sistema de leases. Assim, os objectos activados no servidor s˜ao geridos por este, sendo instanciados apenas quando ocorre a primeira invoca¸c˜ao por parte de um cliente. Este tipo de objectos apenas suporta construtores sem parˆametros e tˆem a sua localiza¸c˜ao bem definida e conhecida, uma vez que est˜ao associados a um URI. Podem ser de dois tipos distintos:

Singleton ou SingleCall. Os objectos do tipo Singleton baseam-se no padr˜ao de desenho com o mesmo nome e portanto dizem respeito a tipos de objectos que s˜ao instanciados uma unica´ vez e com um unico´ ponto global de acesso durante o seu per´ıodo de execu¸c˜ao [3]. Tal como os restantes tipos de objectos remo- tos, estes tamb´em tˆem um tempo de vida pr´e-determinado,

o que significa que os seus clientes n˜ao obter˜ao necessari-

amente sempre uma referˆencia para a mesma instˆancia da classe remota. Este aspecto tem implica¸c˜oes na gest˜ao do estado destes objectos e pode ser contornado, for¸cando a

manuten¸c˜ao do objecto em mem´oria, enquanto o dom´ınio aplicacional do servidor estiver em execu¸c˜ao, atrav´es de uma lease nula. Assim, ´e poss´ıvel que este objecto mantenha um determinado estado entre invoca¸c˜oes e que este seja mod- ificado ou obtido por diferentes clientes. No entanto, este tipo de interac¸c˜ao com objectos Singleton deve ser efectu- ada com alguma precau¸c˜ao, uma vez que o seu acesso n˜ao

´e sincronizado, podendo servir dois clientes concorrentes em

threads de execu¸c˜ao diferentes. Os tipos remotos SingleCall tˆem sempre uma instˆancia por pedido, de modo que cada invoca¸c˜ao por parte de um cliente ´e servida por uma instˆancia diferente, com um estado distinto. Os objectos activados pelos clientes s˜ao instanciados a partir do momento em que este cria um novo objecto do tipo remoto pretendido, com o operador new ou com o m´etodo Activator.CreateInstance(). Neste cen´ario, o cliente pode participar na gest˜ao da vida do objecto remoto, utilizando as j´a mencionadas leases. Tamb´em possibilita a instan- cia¸c˜ao parametrizada bem como a manuten¸c˜ao do estado do objecto por cliente, uma vez que cada cliente tem a sua instˆancia distinta do objecto remoto em execu¸c˜ao no servi- dor.

2.3 Heterogeneidade

A plataforma em estudo resolve de forma elegante e eficaz

os problemas associados `a heterogeneidade, normalmente

discutidos nos sistemas de objectos distribu´ıdos.

2.3.1 Linguagens de Programac¸ ao˜

A existˆencia de um sistema de tipos comum, que garante

a interoperabilidade e integra¸c˜ao dos tipos, atrav´es da im-

posi¸c˜ao de regras e especifica¸c˜ao de um modelo de objectos

comum, resolve o problema da utiliza¸c˜ao de v´arias lingua- gens de programa¸c˜ao no processo de desenvolvimento. Todo o c´odigo produzido por uma linguagem que esteja es- pecificada de acordo com o Common Type System ´e traduzido para uma linguagem interm´edia comum, que mais tarde ´e interpretada pelo runtime e transformada em c´odigo nativo.

2.3.2 Representac¸ ao˜ dos dados

Uma vez que o c´odigo nativo ´e executado em runtimes de- vidamente condicionados e baseados na mesma implementa¸c˜ao,

a heterogeneidade na representa¸c˜ao dos dados n˜ao ´e um

problema, desde que o ambiente de execu¸c˜ao seja comum, isto ´e, tenha como base a mesma vers˜ao de uma determinada implementa¸c˜ao da CLI. A utiliza¸c˜ao de diferentes implementa¸c˜oes e vers˜oes de uma ou mais CLI’s n˜ao garante a representa¸c˜ao homog´enea dos dados, uma vez que a estrutura interna dos tipos pode ter sido alterada, tornando-as efectivamente incompat´ıveis.

2.4 Localizac¸ ao˜

A designa¸c˜ao de servi¸cos remotos na plataforma consiste

na atribui¸c˜ao de URIs bem conhecidos aos objectos e s˜ao

definidos na fase em que estes s˜ao registados na plataforma.

O registo de objectos ´e normalmente realizado pela aplica¸c˜ao

que os instancia, registando os canais de comunica¸c˜ao atrav´es

de

opera¸c˜oes disponibilizadas pela classe ChannelServices e

os

objectos remotos atrav´es da classe RemotingConfiguration.

O

registo de um objecto remoto s´o ´e poss´ıvel mediante a

seguinte informa¸c˜ao:

1. o nome do tipo do objecto remoto.

2. o URI que o designa.

3. o tipo de activa¸c˜ao.

No caso dos objectos activados pelo servidor, esse URI ´e fixo e conhecido, enquanto que nos objectos activados pe- los clientes, esse URI ´e gerado e relativo a uma instˆancia particular do tipo de objecto no servidor.

//

TcpChannel

ChannelServices.RegisterChannel(channel);

registo

de

um

canal

de

=

new

comunica¸c~ao

TcpChannel(4321);

channel

//

RemotingConfiguration.RegisterWellKnownServiceType(

objecto

registo

do

tipo

de

remoto

typeof(MyRemoteObject),

"MyRemoteObjectUri",

WellKnownObjectMode.Singleton

);

Figura 8: Registo t´ıpico de um objecto remoto.

6

2.5 Gest ao˜ do Ciclo de Vida

Nesta plataforma, a problem´atica relativa `a gest˜ao do ciclo de vida dos objectos ´e solucionada com recurso `a utiliza¸c˜ao de leases e sponsorships que, uma vez associadas aos objec- tos remotos, evitam que estes sejam recolhidos pelo mecan- ismo local de recolha de lixo. A excep¸c˜ao a este cen´ario reside nos objectos single-call activados no servidor, que s˜ao desactivados imediatamente ap´os uma invoca¸c˜ao sobre as suas opera¸c˜oes.

2.5.1 Leases e Sponsors

Tal como os restantes sistemas de objectos distribu´ıdos, em .NET Remoting a gest˜ao de ciclo de vida est´a associada ao mecanismo de recolha de lixo, que mant´em informa¸c˜ao acerca dos objectos em utiliza¸c˜ao pelos clientes. Quando um objecto deixa de ser referenciado pelos clientes, ´e recol- hido e eventualmente destru´ıdo, sendo libertada a mem´oria anteriormente atribu´ıda. Este processo ´e eficaz num cen´ario onde as aplica¸c˜oes par- tilham o mesmo processo de execu¸c˜ao (a mesma CLR). Num

cen´ario distribu´ıdo, a situa¸c˜ao ´e diferente, uma vez que um objecto pode n˜ao ter clientes locais, mas sim clientes que est˜ao em execu¸c˜ao em processos e m´aquinas diferentes, onde

a recolha prematura de um objecto resultaria na invalida¸c˜ao da referˆencia remota possu´ıda pelos clientes.

A solu¸c˜ao implementada na plataforma .NET envolve a

utiliza¸c˜ao de leases e funciona da seguinte forma: o acesso

a um objecto no servidor por parte de um cliente resulta

na associa¸c˜ao deste a um objecto lease, que mantˆem, entre outras propriedades, um per´ıodo de tempo durante o qual

o objecto servidor n˜ao dever´a ser recolhido. O lease man-

ager, respons´avel pela gest˜ao das associa¸c˜oes entre objectos

e leases, d´a in´ıcio `a contagem decrescente do tempo de lease

a partir do momento em que a primeira referˆencia ´e envi- ada para fora do seu dom´ınio de execu¸c˜ao. Esta entidade tamb´em mant´em uma referˆencia para o objecto servidor, evitando assim a sua recolha para destrui¸c˜ao. Uma vez ex- pirada a lease de um objecto, a CLR assume que n˜ao existem clientes a utilizar referˆencias remotas e descarta tamb´em a sua referˆencia local [6]. No entanto, n˜ao s˜ao dadas garantias de que n˜ao exis- tam ainda clientes que possuam referˆencias para os objec-

tos remotos.

E ent˜ao necess´ario providenciar uma forma de

estes poderem extender as leases. Aqueles clientes que pre- cisam de ser contactados quando o tempo de vida de um objecto remoto termina devem recorrer a um objecto spon- sor, registando-o na lease respectiva. Assim, o gestor de leases percorre a lista de sponsors associada `a lease do ob- jecto em quest˜ao e identifica se h´a ou n˜ao necessidade de extender o seu tempo de vida.

´

2.5.2 Propriedades das Leases

Uma lease ´e instanciada com valores atribu´ıdos por omiss˜ao `as suas propriedades (ver Figura 9), mas que podem ser al- terados antes de serem registados os objectos no servidor, quer programaticamente, quer atrav´es dos ficheiros de con- figura¸c˜ao da aplica¸c˜ao.

A propriedade RenewOnCallTime tem um valor de tempo

adicional que ´e automaticamente acrescentado ao tempo de vida do objecto caso sejam invocados m´etodos sobre este, perto da expira¸c˜ao da sua lease. Esta renova¸c˜ao do tempo de lease s´o ´e efectuada caso o restante tempo de vida do objecto seja inferior ao valor atribu´ıdo `a propriedade anteri-

public

sealed

class

LifetimeServices

 

{

 

TimeSpan

LeaseManagerPollTime

{

get;

set;

}

TimeSpan

InitialLeaseTime

 

{

get;

set;

}

TimeSpan

RenewOnCallTime

{

get;

set;

}

TimeSpan

SponsorshipTimeout

{get;

set;

 

}

static

LifetimeServices()

 

{

LeaseManagerPollTime

=

TimeSpan.FromSeconds(10);

LeaseTime

=

TimeSpan.FromMinutes(5);

 

RenewOnCallTime

=

TimeSpan.FromMinutes(2);

SponsorshipTimeout

=

TimeSpan.FromMinutes(2);

}

}

Figura 9:

Classe

LifetimeServices

ormente mencionada, evitando assim que um objecto remoto

que seja bastante solicitado pelos seus clientes aumente pro- gressivamente o seu tempo de vida.

A propriedade LeaseManagerPollTime indica a dura¸c˜ao

do intervalo de tempo que dever´a decorrer entre a verifica¸c˜ao dos tempos das leases, que por omiss˜ao ´e de 10 segundos, enquanto que a propriedade SponsorshipTimeout especifica

o tempo que o servidor dever´a esperar por respostas dos

clientes remotos quando inquire estes acerca do estado da sua sponsorship. Esta propriedade ´e importante pois ´e a partir deste valor que s˜ao toleradas falhas de comunica¸c˜ao com os clientes, sendo estes removidos da lista de sponsors da lease caso n˜ao respondam dentro do intervalo de tempo estabelecido. Um objecto remoto pode tamb´em alterar as propriedades

do seu ciclo de vida ap´os a sua instancia¸c˜ao, fornecendo uma implementa¸c˜ao para o m´etodo InitializeLifetimeService

e devolvendo um objecto do tipo ILease.

2.5.3 Sponsors

Como foi referido anteriomente, um sponsor ´e utilizado para possibilitar um pedido de renova¸c˜ao do lease por parte do cliente, quando este est´a prestes a expirar. Este processo de renova¸c˜ao envolve a invoca¸c˜ao do m´etodo Renewal no objecto sponsor, pelo gestor de leases. Uma vez que os objectos sponsor est˜ao associados aos clientes e tˆem de ser registados no servidor, ter˜ao de derivar da classe MarshalByRefObject e ser enviados por referˆencia, ou ent˜ao marcados como Serializable e enviados por valor. Na primeira hip´otese, o cliente dever´a garantir a manuten¸c˜ao de uma referˆencia para este objecto remoto e remover o seu registo quando j´a n˜ao for necess´ario, ganhando nesta situa¸c˜ao a vantagem de poder controlar as suas decis˜oes com base em eventos ou propriedades associadas ao cliente. Por outro lado, se o objecto sponsor for enviado por valor, ´e cri- ada uma c´opia no servidor que, apesar de ser transferida de forma mais eficiente , apenas poder´a basear as suas decis˜oes nas propriedades do servidor.

2.6 Persist enciaˆ

O suporte ao armazenamento de tipos de objectos num

reposit´orio de dados persistente n˜ao constitui um servi¸co in- trinsecamente ligado ao .NET Remoting, mas est´a presente na plataforma .NET como um componente gen´erico para o

7

tratamento e persistˆencia de estruturas de dados relacionais, designado por ADO.NET. Esta API em conjunto com o processo de serializa¸c˜ao de objectos j´a abordado, poderia estar na base da imple- menta¸c˜ao de um servi¸co de persistˆencia orientado para o armazenamento dos objectos remotos, particularmente util´ na salvaguarda a longo-prazo do estado de execu¸c˜ao de servi- dores.

2.7 Interoperabilidade

A interoperabilidade da plataforma .NET Remoting em

rela¸c˜ao a outros sistemas de objectos distribu´ıdos assenta

sobretudo no protocolo SOAP e no mecanismo de pedi- dos de invoca¸c˜oes remotas facultado, expressos sob a forma de mensagens SOAP. Este protocolo especifica um formato XML normalizado, que permite a inclus˜ao de defini¸c˜oes de tipos e dados estruturados, independente da plataforma e linguagem de programa¸c˜ao utilizadas. Esta possibilidade de oferecer servi¸cos web, baseados em XML, a clientes poten- cialmente desenvolvidos sobre outras plataformas e arqui- tecturas, garante que as mensagens podem ser trocadas e entendidas entre sistemas diferentes, escondendo assim os detalhes de implementa¸c˜ao dos servi¸cos remotos.

2.8 Configurabilidade

De forma a introduzir alguma flexibilidade na configura¸c˜ao

dos servi¸cos oferecidos pelos objectos remotos, a plataforma suporta o carregamento de determinadas propriedades a par- tir de ficheiros, sem ser necess´ario recompilar o c´odigo.

´

E

poss´ıvel ent˜ao especificar num ficheiro de configura¸c˜ao

a porta e o tipo de canal utilizado no estabelecimento de liga¸c˜oes ao objecto remoto, o seu modelo de activa¸c˜ao, o URI de acesso, entre outras propriedades importantes (ver Figura 10).

<configuration>

<system.runtime.remoting>

<application

name="MyServer">

<service>

<wellknown

mode="Singleton"

type="MyServerImpl,

MyServerLib"

objectUri="MyURI"

/>

</service>

<channels>

<channel

ref="tcp"

port="8080"

/>

</channels>

</application>

</system.runtime.remoting>

</configuration>

Figura 10: Exemplo de um ficheiro de configura¸c˜ao

2.9 Ambientes de Execuc¸ ao˜

Uma vez que os objectos remotos s´o podem ser activa- dos ap´os efectuado o seu registo e o dos seus canais de comunica¸c˜ao, esse processo dever´a ser efectuado por uma aplica¸c˜ao designada para esse fim. Essa aplica¸c˜ao dever´a estar em execu¸c˜ao durante todo o ciclo de vida dos objectos registados. Em ambientes Microsoft Windows, essa aplica¸c˜ao pode ser substitu´ıda por um servi¸co gen´erico desenvolvido com esse objectivo, ou ent˜ao associada a um de dois servi¸cos

j´a existentes: o IIS (Internet Information Services) ou aos

servi¸cos COM+.

2.9.1 Integrac¸ ao˜ no IIS

O IIS ´e um servidor web e normalmente est´a sempre em

execu¸c˜ao num ambiente Windows. Como tal, presta-se a ser um bom anfitri˜ao aos componentes remotos que se querem

disponibilizar, apesar de estar limitado `a utiliza¸c˜ao de canais HttpChannel. Por outro lado, possibilita uma configura¸c˜ao r´apida das restri¸c˜oes de seguran¸ca impostas aos componentes

e a altera¸c˜ao da sua configura¸c˜ao sem ser necess´ario re- iniciar o servi¸co.

2.9.2 Integrac¸ ao˜ nos servic¸os COM+

Outra op¸c˜ao passa por tirar partido das funcionalidades oferecidas pelo ambiente COM+, tais como o suporte a transac¸c˜oes distribu´ıdas, seguran¸ca baseada em roles, e pool- ing de objectos. Um componente remoto pode participar do contexto de execu¸c˜ao dos servi¸cos COM+ derivando da classe ServicedComponent. Esta classe, e o espa¸co de nomes System.EnterpriseServices, possibilita a utiliza¸c˜ao de atrib- utos particulares ao COM+ num objecto em execu¸c˜ao na CLR e a todos os benef´ıcios que da´ı resultam.

3. EXEMPLOS

Procedeu-se ao desenvolvimento de um conjunto de exem- plos simples, demonstrativos das funcionalidades disponibi- lizadas pelo infra-estrutura de Remoting, sobre uma imple- menta¸c˜ao da CLI open source e compat´ıvel com sistemas UNIX, designada por Mono e dispon´ıvel em http://www.mono- project.com/. Esta distribui¸c˜ao implementa toda a funcionalidade da

vers˜ao 1.1 da plataforma .NET dispon´ıvel para sistemas op- erativos Microsoft Windows e ainda extende a distribui¸c˜ao

´

base com uma s´erie de m´odulos adicionais.

por uma m´aquina virtual, que constitui o ambiente con- trolado de execu¸c˜ao das aplica¸c˜oes, um compilador just-in- time, para a linguagem interm´edia, uma API que reproduz

as Framework Class Libraries da Microsoft e um compilador

de C#. S˜ao apresentadas, no apˆendice deste documento, listagens de alguns dos exemplos desenvolvidos, sendo que os restantes estar˜ao dispon´ıveis num ficheiro que dever´a acompanhar este trabalho.

E composta

˜

4. CONCLUS OES

A infra-estrutura de Remoting, integrada na plataforma

.NET, apresenta caracter´ısticas comuns a outros sistemas de objectos distribu´ıdos, n˜ao alheio ao facto de esta ter sido a abordagem mais recente ao suporte de invoca¸c˜oes em objec- tos remotos e toda a problem´atica em redor. Tal como o CORBA, DCOM e Java/RMI, em Remoting

a interoperabilidade entre objectos desenvolvidos em difer-

entes linguagens, possibilitando a execu¸c˜ao e comunica¸c˜ao entre estes num ambiente CLI, onde o tratamento de erros estabelecido segue um modelo at-most-once.

A utiliza¸c˜ao de proxys como mecanismo de atingir um

modelo de transparˆencia de acesso ´e comum a todos os sis-

temas referidos, sendo de real¸car que em Remoting, a cria¸c˜ao

e manipula¸c˜ao dos objectos deste tipo ´e completamente in- vis´ıvel para o utilizador ou programador.

O mecanismo de leases constitui o modelo de recolha de

objectos para os quais j´a n˜ao existem referˆencias e est˜ao tamb´em implementadas variadas formas de suporte `a ac- tiva¸c˜ao dinˆamica dos objectos servidores. Em suma, a infra-estrutura de Remoting tem bastantas semelhan¸cas com a do Java/RMI, mas oferece de raiz, em determinados aspectos, mais funcionalidades associadas ao tratamento dos objectos remotos, e na configura¸c˜ao e ex- tens˜ao dos canais de comunica¸c˜ao. A interoperabilidade com outras plataformas atrav´es de protocolos como o SOAP e HTTP evidencia tamb´em uma abertura para a integra¸c˜ao entre sistemas com diferentes implementa¸c˜oes.

5. REFERÊNCIAS

[1] W. Emmerich. Engineering Distributed Objects. John Wiley and Sons, Ltd, 2000. [2] B. et al. Network Objects. DIGITAL, Inc., 1995. [3] G. et al. Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley, 1995.

[4] M. et al. Microsoft .NET Remoting. Microsoft Press,

2003.

[5] E. International. Standard ECMA-335: Common Language Infrastructure. ECMA International, 2005. [6] J. Lowy. Managing the lifetime of remote .net objects

with leasing and sponsorhip. MSDN Magazine, Dezembro 2003.

[7] SUN. Java RMI Specification. Sun Microsystems, Inc.,

1998.

APÊNDICES

A. LISTAGENS

Apresentamos em seguida implementa¸c˜oes de alguns ex- emplos desenvolvidos no ˆambito de uma demonstra¸c˜ao das capacidades da plataforma .NET Remoting, conforme de- talhadas no texto.

A.1 Hello World - Client Activated

A.1.1 RemoteObject.cs

using

System;

using

System.Runtime.Remoting;

´e poss´ıvel solicitar a execu¸c˜ao de opera¸c˜oes em objectos res- identes noutros contextos de execu¸c˜ao, num ambiente dis-

namespace

com.mgcm.net.remoting

 

`

tribu´ıdo.

A semelhan¸ca do Java/RMI, a inclus˜ao no modelo

{

de objectos de objectos n˜ao-remotos exige uma diferencia¸c˜ao

public

class

RemoteObject

:

MarshalByRefObject

no seu tratamento a n´ıvel de tipos, e, como nos sistemas

{

acima mencionados, todo o objecto remoto ´e identificado a

public

RemoteObject()

 

partir de uma referˆencia que assegura a transparˆencia de

{

localiza¸c˜ao.

}

A

Common Type System estabelece a separa¸c˜ao entre a

no¸c˜ao de interfaces e implementa¸c˜oes, 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;

}

A.1.2 RemoteServer.cs

using

System;

using

System.Runtime.Remoting;

using

System.Runtime.Remoting.Channels;

using

System.Runtime.Remoting.Channels.Tcp;

namespace

{

com.mgcm.net.remoting

public

{

class

RemoteClient

public

{

static

int

Main(string[]

args)

TcpChannel

ChannelServices.RegisterChannel(tcp);

new

tcp

=

TcpChannel();

namespace

com.mgcm.net.remoting

{

public

{

class

RemoteServer

public

{

static

int

Main(string[]

args)

TcpChannel

ChannelServices.RegisterChannel(tcp);

new

tcp

=

TcpChannel(8080);

RemoteObject

obj

=

(RemoteObject)

Activator.GetObject( typeof(com.mgcm.net.remoting.RemoteObject),

"tcp://localhost:8080/HelloWorld");

}

Console.WriteLine(obj.HelloWorld());

return

0;

RemotingConfiguration.RegisterWellKnownServiceType(

}

}

typeof(RemoteObject),

"HelloWorld",

WellKnownObjectMode.SingleCall);

A.3 Execuc¸ ao˜ de C odigo´

M ovel´

}

}

}

System.Console.WriteLine("server

System.Console.ReadLine();

return

0;

A.1.3 RemoteClient.cs

running

");

using

System;

using

System.Runtime.Remoting;

 

using

System.Runtime.Remoting.Channels;

using

System.Runtime.Remoting.Channels.Tcp;

namespace

com.mgcm.net.remoting

 

{

public

class

RemoteClient

 

{

 

public

static

int

Main(string[]

args)

{

 

TcpChannel

tcp

=

new

TcpChannel();

ChannelServices.RegisterChannel(tcp);

RemoteObject

obj

=

(RemoteObject)

Activator.CreateInstance(

 

typeof(com.mgcm.net.remoting.RemoteObject));

Console.WriteLine(obj.HelloWorld());

return

0;

 

}

}

}

A.2 Hello World - Server Activated

A.2.1 RemoteClient.cs

A.3.1 Interfaces.cs

namespace

com.mgcm.net.remoting

{

public

interface

ITask

{

void

exec();

}

public

interface

IAgent

{

void

run();

}

public

interface

IAgentHost

{

void

accept(IAgent

agent);

}

}

A.3.2 Tasks.cs

using

System;

namespace

com.mgcm.net.remoting

{

[Serializable]

public

class

TaskHello:

ITask

{

public

TaskHello():base()

 

{

}

public

void

exec()

{

System.Console.WriteLine("Hello

World");

}

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;

 

{

public

class

AgentHost:

MarshalByRefObject,

IAgentHost

using

using

System.Runtime.Remoting;

System.Runtime.Remoting.Channels;

 

{

 

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)

 

);

t.Start();

 

ChannelServices.RegisterChannel(channel);

 

}

RemotingConfiguration.RegisterWellKnownServiceType(

public

{

void

accept(IAgent

agent)

 

typeof(AgentHost),

"AgentHost",

 

}

agents.Push(agent);

 

WellKnownObjectMode.Singleton

);

 

public

void

execAgents()

 

}

System.Console.ReadLine();

{

}

 

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

ChannelServices.RegisterChannel(channel);

channel

=

new

TcpChannel();

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);

}

}

}