.NET Remoting

Um estudo ao suporte de invocacoes em objectos remotos na plataforma .NET ¸˜
Milton Moura
Faculdade de Ciencias e Tecnologia ˆ Universidade Nova de Lisboa Pos-Graduacao em Enga Informatica ¸˜ ´ ´

Ricardo Seabra
Faculdade de Ciencias e Tecnologia ˆ Universidade Nova de Lisboa Licenciatura em Enga Informatica ´

miltonmoura@gmail.com RESUMO
Existe hoje em dia um n´mero consider´vel de tecnologias u a orientadas para a programa¸˜o de sistemas de objectos disca tribu´ ıdos, como s˜o exemplo disso o CORBA, o Java/RMI, o a DCOM e, mais recentemente, o .NET Remoting. Qualquer uma delas oferece um agregado de servi¸os e funcionalidades c que diferem na sua abordagem e implementa¸˜o, tornandoca as mais ou menos complexas e apropriadas para determinados cen´rios de utiliza¸˜o. a ca Este trabalho resulta de uma an´lise ao suporte de ina voca¸˜es em objectos remotos na plataforma de desenvolvico mento .NET, tendo como ambiente de execu¸˜o a impleca menta¸˜o multi-plataforma da especifica¸˜o CLI denomica ca nada Mono, e pretende expor os v´rios aspectos dos servi¸os a c disponbilizados pelo componente .NET Remoting, bem como a sua arquitectura e funcionamento interno. Numa vertente pr´ctica, s˜o apresentados alguns exempa a los de diferentes t´cnicas normalmente utilizadas em ambie entes de sistemas de objectos distribu´ ıdos, com o objectivo de oferecer assim uma vis˜o comparativa deste suporte em a rela¸˜o a outros j´ estudados. ca a

ricardo.seabra@gmail.com
infra-estruturas deste tipo, como os stubs, o processo de marshaling e a IDL [1]. A restante plataforma .NET ´ constitu´ por um ambie ıda ente controlado de execu¸˜o de c´digo, designado por CLR ca o (Common Language Runtime), um gestor de mem´ria, reo spons´vel pela recolha autom´tica de referˆncias n˜o utia a e a lizadas, um sistema de tipos unificado (Common Type System) que permite a interoperabilidade entre objectos implementados em diferentes linguagens de programa¸˜o, compica ladas por uma ferramenta que implemente a CLS (Common Language Specification), e um conjunto de APIs, separados em m´dulos l´gicos, que enriquece o modelo de objectos base o o fornecido [5].

2.

.NET REMOTING

1.

INTRODUCAO ¸˜

As tecnologias de suporte aos sistemas distribu´ ıdos de objectos permitem que componentes em execu¸˜o numa deca termina m´quina sejam acedidos por aplica¸˜es ou objectos a co em execu¸˜o noutras m´quinas distintas. Tecnologias como ca a o CORBA, o Java/RMI, o DCOM e o .NET Remoting s˜o a exemplos de sistemas deste tipo e, apesar de estarem implementados de forma muito diferente e com funcionalidades distintas, mantˆm algumas semelhan¸as: e c • Os objectos tˆm uma identidade unica e podem ter um e ´ estado de execu¸˜o. ca • A utiliza¸˜o de objectos remotos tem a mesma sem˜ntica ca a dos objectos locais. • Est˜o associados a um modelo de componentes, onde a os detalhes de implementa¸˜o est˜o escondidos. ca a • Tˆm modelos de tolerˆncia a falhas bem definidos. e a A implementa¸˜o de suporte ` invoca¸˜o de objectos reca a ca motos no .NET Remoting ´ semelhante ` do Java/RMI [7] e a em muitos aspectos, pois ambos tˆm como base a especie fica¸˜o de Birrel et al [2] para RPC’s (Remote Procedure ca Calls), que introduziu os conceitos b´sicos utilizados nas a 1

Integrado na especifica¸˜o da plataforma Microsoft .NET, ca o componente .NET Remoting permite o desenvolvimento de aplica¸˜es distribu´ co ıdas, onde os objectos participantes podem ser executados em m´quinas e processos diferentes e a em dominios aplicacionais distintos. Na g´nese do .NET Remoting est´ uma implementa¸˜o e a ca abstracta de comunica¸˜o entre processos que separa os obca jectos remotos e seus potenciais clientes do mecanismo de comunica¸˜o entre si, tornando-se assim uma plataforma ca flex´ ıvel e extens´ ıvel, onde os protocolos de comunica¸˜o e ca ´ formatos de serializa¸˜o podem ser facilmente alterados. E ca tamb´m agn´stica ao modelo da aplica¸˜o, possibilitando a e o ca interoperabilidade entre aplica¸˜es Web, servi¸os de sistema co c ou programas executados na consola. A plataforma disponibiliza ainda um conjunto de servi¸os c comuns em ambientes de middleware, como o suporte ` aca tiva¸˜o de objectos remotos, gest˜o do seu ciclo de vida e ca a seguran¸a nos canais de mensagens. c

2.1

Meta-Modelo de Objectos e Definicao de Interfaces ¸˜

O c´digo executado na plataforma .NET tem v´rios n´ o a ıveis de isolamento, sendo que num processo da CLR podem estar em execu¸˜o v´rios dom´ ca a ınios aplicacionais. Em qualquer dom´ ınio aplicacional s˜o dadas as seguintes garantias: a 1. Uma aplica¸˜o pode ser parada de forma indepenca dente. 2. Uma aplica¸˜o n˜o pode aceder directamente a c´digo ca a o e recursos de outra aplica¸˜o. ca 3. Uma falha na aplica¸˜o n˜o afecta as restantes aplica¸˜es. ca a co

4. A configura¸˜o da aplica¸˜o determina o local de onde ca ca o c´digo ´ carregado e a sua vers˜o. o e a Um dom´ ınio aplicacional pode ainda ser dividido em contextos, que asseguram uma s´rie de restri¸˜es e semˆntica de e co a seguran¸a no acesso aos objectos que neles se encontrem em c execu¸˜o. Por omiss˜o, todo o dom´ ca a ınio aplicacional cont´m e pelo menos um contexto, onde s˜o criados todos os objeca tos, excepto aqueles que necessitam de um novo contexto especializado.

Os tipos de objectos remotos podem ser classificados de acordo com trˆs categorias: marshal-by-value, marshal-bye reference ou context-bound. As instˆncias dos tipos marshala by-value podem ser enviadas entre dom´ ınios aplicacionais atrav´s de um processo de serializa¸˜o, que corresponde ` e ca a codifica¸˜o do estado actual de um objecto numa sequˆncia ca e de bits. A recep¸˜o de um objecto deste tipo resulta na ca cria¸˜o de uma c´pia no destino, com o mesmo estado do ca o objecto original. Os objectos deste tipo s˜o caracterizaa dos por um atributo especificado na sua defini¸˜o, o atribca uto Serializable. No entanto, ´ poss´ e ıvel que um objecto definido com este atributo contenha propriedades que n˜o a 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 a quando se pretende manter uma unica instˆncia desse tipo ´ a acess´ num determinado dom´ ıvel ınio aplicacional, sendo passada uma referˆncia dessa instˆncia aos seus clientes, em e a vez de uma c´pia serializada. Assim, para que os objeco tos possam ser acedidos remotamente, estes tˆm de derivar e do tipo MarshalByRefObject (ver Figura 2), de forma a suportar essa funcionalidade. As referˆncias envolvidas neste e processo s˜o objectos do tipo ObjRef. a [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¸˜o do objecto remoto t´ ca ıpico, passado por referˆncia, e que neste caso est´ restrito ao contexto de execu¸˜o em que a ca ´ instanciado. Isto significa que o seu acesso, inclusive a pare tir do mesmo dom´ ınio aplicacional, envolve sempre o envio de uma referˆncia remota para os objectos clientes, em vez e da invoca¸˜o local normal que seria de esperar em situa¸˜es ca co deste tipo. Essa funcionalidade ´ adquirida derivando do e tipo ContextBoundObject. Os restantes tipos n˜o-remotos definidos para a plataforma a .NET s˜o suportados pela API de Remoting de forma transa parente, possibilitando a utiliza¸˜o de qualquer classe, inca terface, enumera¸˜o e objecto, sem quaisquer limita¸˜es. ca co Partindo do princ´ ıpio que tanto os clientes como os objectos servidor est˜o contidos em plataformas de execu¸˜o a ca idˆnticas, isto ´, em CLRs baseadas numa mesma vers˜o e e a de implementa¸˜o, a interoperabilidade a n´ ca ıvel de tipos de dados est´ solucionada ` partida. a a 2

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

2.1.1

Objectos

O .NET Remoting possbilita a invoca¸˜o de m´todos soca e ´ bre objectos remotos, em execu¸˜o num CLR host. E inca diferente ao sistema a linguagem em que est˜o implementaa dos os objectos servidores e objectos clientes, podendo esta ser distinta. O sistema unificado de tipos da plataforma gere a representa¸˜o interna dos objectos e garante assim a sua ca interoperabilidade. A invoca¸˜o remota de m´todos depende da obten¸˜o de ca e ca uma referˆncia para o objecto remoto, referˆncia esta que e e cont´m uma s´rie de meta-dados necess´rios para que o e e a cliente efectue a invoca¸˜o de forma transparente, utilizando ca uma semˆntica de acesso idˆntica ` dos objectos locais. a e a A obten¸˜o dessa referˆncia ´ levado a cabo atrav´s de um ca e e e canal de comunica¸˜es estabelecido com o servidor, desigco nado por um URI (Universal Resource Identifier ) de acesso unico. Ao iniciar, ´ da responsabilidade do servidor registar ´ e ambos estas propriedades na plataforma.

2.1.2

Tipos

Com o objectivo de possibilitar a interac¸˜o entre objectos ca residentes em diferentes n´ ıveis de isolamento da plataforma, os tipos de objectos objectos podem ser classificados de remotos ou n˜o-remotos. Um tipo ´ considerado remoto se: a e 1. As suas instˆncias podem atravessar os n´ a ıveis de isolamento da plataforma. 2. Outros objectos podem aceder a instˆncias do tipo, a atravessando os n´ ıveis de isolamento da plataforma. Qualquer tipo de objecto que n˜o satisfa¸a estas proa c priedades, ´ n˜o-remoto. e a

2.1.3

Atributos

Um tipo de objecto remoto pode definir atributos, designados por propriedades na plataforma .NET, e especificar se estes s˜o s´ de leitura ou de leitura e escrita. No entanto, a a o sua implementa¸˜o interna, forma de acesso e representa¸˜o ca ca s˜o em tudo idˆnticas aos dos m´todos. a e e interface IRemoteObject { int MyRemoteMethod(); // propriedade s´ de leitura o double MyFloatProperty { get; } // propriedade de leitura-escrita int MyIntProperty { get; set; } } Figura 3: Exemplo de defini¸˜o de propriedades ca

delegate string MyDelegate(int myValue); string DoSomething(int myValue); MyDelegate md = new MyDelegate(DoSomething); // invoca¸~o ass´ncrona ca ı IAsyncResult ar = md.BeginInvoke( someValue, null, null); // obten¸~o do resultado ca string result = md.EndInvoke(ar); Figura 4: Exemplo de invoca¸˜o ass´ ca ıncrona ´ retorno da fun¸˜o. E tamb´m suportado um modo de inca e voca¸˜o ass´ ca ıncrona num s´ sentido, ou seja, os m´todos n˜o o e a podem possuir retorno ou parˆmetros de sa´ a ıda. Apesar de existir uma API de reflex˜o na especifica¸˜o a ca da CLI (System.Reflection), esta n˜o est´ integrada com a a o Remoting de forma a possibilitar a invoca¸˜o dinˆmica ca a de opera¸˜es. Est´ portanto limitada ` invoca¸˜o est´tica co a a ca a e dependente do acesso ` defini¸˜o dos tipos dos objectos a ca num assembly local ou registado na GAC (Global Assembly Cache).

2.1.4

Operacoes ¸˜

Designados por m´todos, as opera¸˜es em Remoting poe co dem ser invocadas desde que declaradas como p´blicas na u implementa¸˜o do tipo de objecto remoto. Caso o objecto ca remoto seja uma implementa¸˜o de um ou mais interfaces, ca ent˜o todos os m´todos implementados, necess´rios para a e a satisfazer o contrato, s˜o p´blicos. a u A semˆntica de invoca¸˜o das opera¸˜es remotas ´ muito a ca co e semelhante ` dos m´todos locais, uma vez que os parˆmetros a e a podem ser passados por referˆncia ou por valor. A pase sagem de um parˆmetro por referˆncia significa que ´ pasa e e sado um apontador com a informa¸˜o necess´ria para que ca a a opera¸˜o o manipule, tal como a sua localiza¸˜o e outros ca ca dados necess´rios. A passagem de objectos por valor resulta a na cria¸˜o de uma c´pia no contexto de execu¸˜o do m´todo ca o ca e invocado, idˆntica ` do objecto submetido. e a No entanto, quando est˜o envolvidos objectos remotos, a a sua passagem como parˆmetro de um m´todo remoto dea e pende do seu tipo, mais precisamente, se este ´ marshal-bye reference ou marshal-by-value.

2.1.6

Tratamento de erros

O tratamento de erros, ` semelhan¸a do que acontece a c na restante plataforma, ´ efectuada atrav´s da propaga¸˜o e e ca de excep¸˜es, objectos do tipo Exception que dever˜o ser co a definidos como serializ´veis, de forma a poderem ser transa formadas e enviados pelos canais de comunica¸˜o definidos ca entre os objectos remotos e clientes envolvidos. Em particular, os erros com origem na infra-estrutura de Remoting, lan¸am apenas um tipo de excep¸˜o: o RemotingException. c ca Uma excep¸˜o deste tipo pode ser levantada por in´meras ca u raz˜es, entre as quais: o ´ • E instanciado um tipo de objecto remoto que n˜o deriva a de MarshalByRefObject. • Especifica¸˜o inv´lida do ponto de acesso de um tipo ca a de objecto remoto, isto ´, o URI est´ mal formado. e a • Protocolos de comunica¸˜o diferentes entre os clientes ca e os objectos servidor. • A invoca¸˜o de opera¸˜es sobre objectos remotos que ca co n˜o est˜o em execu¸˜o, nem foram activados. a a ca

2.1.5

Invocacoes ¸˜

A semˆntica de invoca¸˜es nesta plataforma ´ do tipo ata co e most-once, o que significa que a recep¸˜o de uma excep¸˜o ca ca resultante de uma invoca¸˜o remota indica que o m´todo ca e alvo poder´ n˜o ter sido executado. Por outro lado, a inexa a istˆncia de erros constitui uma garantia de que a opera¸˜o e ca foi executada com sucesso no objecto remoto. Podem ser efectuados trˆs tipos diferentes de invoca¸˜es e co sobre objectos remotos: s´ ıncronas, ass´ ıncronas, e ass´ ıncronas num s´ sentido (oneway). O modo s´ o ıncrono consiste no bloqueio do cliente, ap´s a invoca¸˜o, at´ que alguma resposta o ca e ou excep¸˜o seja enviada pelo servidor ou pela plataforma. ca Para fazer face ao potencial fraco desempenho das chamadas s´ ıncronas, o .NET Remoting suporta um mecanismo de invoca¸˜es ass´ co ıncronas, assente na utiliza¸˜o de delegates. Os ca delegates fornecem um mecanismo de callback com verifica¸˜o ca de tipos, permitindo a invoca¸˜o ass´ ca ıncrona de opera¸˜es loco cais ou remotas (ver Figura 4). Assim, a invoca¸˜o do m´todo ´ feita em dois passos: em ca e e primeiro lugar despoleta-se a invoca¸˜o da opera¸˜o remota ca ca a partir do m´todo BeginInvoke(). Este m´todo retorna e e um objecto IAsyncResult que ir´ permitir obter o valor de a 3

2.1.7

Sub-tipos e heranca m´ ltipla ¸ u

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

2.1.8

Polimorfismo

O suporte ao polimorfismo est´ estaticamente restricto a pela heran¸a de m´ltiplos interfaces. A qualquer objecto c u do sistema est´ associado um tipo est´tico, sendo apenas a a poss´ atribu´ a este instˆncias de objectos cujo tipo est´tico ıvel ır a a

seja um super-tipo do objecto em quest˜o. E poss´ ent˜o a ´ ıvel a redefinir determinadas opera¸˜es herdadas pelos sub-tipos co e determinar a execu¸˜o da opera¸˜o correcta atrav´s de ca ca e mecanismos de late-binding. Esta garantia de consistˆncia da representa¸˜o dos tipos e ca distribu´ ıdos e a coerˆncia do modelo de objectos permite ine stituir uma no¸˜o de polimorfismo distribu´ ca ıdo, abrindo portas ao suporte de migra¸˜o de c´digo entre dom´ ca o ınios aplicacionais e contextos de execu¸˜o distintos. ca

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

2.2

Arquitectura

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

Figura 6: Entidades envolvidos na invoca¸˜o de um ca m´todo remoto. e

2.2.1

Referˆ ncias Remotas e

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ˆncia local da classe TransparentProxy, que cont´m uma a e lista de todas classes e m´todos dos interfaces do objecto ree moto. Assim que esta classe ´ criada, todas as invoca¸˜es e co sobre ela s˜o interceptados pelo runtime, de forma a dea terminar a sua validade e a existˆncia de uma instˆncia do e a objecto alvo no mesmo dom´ ınio aplicacional em que o proxy est´ em execu¸˜o. Se existir, ent˜o ´ feito um encamina ca a e hamento simples para o m´todo invocado no objecto local. e Caso contr´rio, ´ criado um objecto do tipo IMessage, onde a e s˜o colocados os parˆmetros submetidos ao m´todo remoto a a e (caso existam), e encaminhada a mensagem para um objecto RealProxy, atrav´s do m´todo Invoke(). Esta classe e e ´ respons´vel pelo encaminhamento das mensagens para o e a objecto remoto, atrav´s de canais registados no servidor. e Uma vez recebida a mensagem de invoca¸˜o no dom´ ca ınio aplicacional ou contexto de destino, o m´todo ´ invocado e e 4

As referˆncias para os objectos remotos, envolvidos no e processo descrito anteriormente, s˜o do tipo ObjRef e contˆm a e toda a informa¸˜o necess´ria para a cria¸˜o dos proxys j´ ca a ca a mencionados. A referˆncia cont´m, entre outros dados, o e e URI que constitui o ponto de acesso conhecido para o objecto em quest˜o, uma s´rie de meta-dados que descrevem o a e 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, e ca a u entre outros. Dados acerca de todos os tipos da hierarquia de deriva¸˜o tamb´m s˜o agrupados nesta referˆncia e serica e a e alizados de forma a serem enviados ao cliente. Ainda ´ ine clu´ informa¸˜o relativa ao contexto de execu¸˜o, dom´ ıda ca ca ınio aplicacional e processo que cont´m o objecto associado ` ree a ferˆncia, bem como a identifica¸˜o do tipo de canal, endere¸o e ca c e porta que dever˜o ser utilizados nos pedidos de invoca¸˜o a ca remota.

2.2.2

Mensagens

Na base do suporte a invoca¸˜es sobre objectos remoco tos est˜o as mensagens, um tipo de objecto que abstrai o a processo de invoca¸˜o de m´todos de uma forma orientada ca e a objectos. Assim, uma mensagem pode encapsular a invoca¸˜o de m´todos, argumentos de entrada e valores de ca e retorno, invoca¸˜es a construtores de objectos, lan¸amento co c de excep¸˜es, entre outros. Os objectos de mensagens imco plementam o tipo IMessage e s˜o serializ´veis. a a

2.2.3

Canais

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

protocolos e formatos na transmiss˜o dos dados. No entanto, a 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 codificar as mensagens. O SOAP ´ um protocolo baseado em e XML, desenhado para permitir a invoca¸˜o de procedimenca tos remotos sobre HTTP, de forma a superar as restri¸˜es co impostas pelas firewalls em redes de larga escala. Em ambientes mais controlados, o TcpChannel verifica-se uma alternativa mais eficaz, uma vez que, por defeito, utiliza um formato bin´rio, minimizando assim o tamanho das mena 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¸˜o de daca dos, tamb´m implementam os tipos IChannelReceiver e e IChannelSender. Os canais tˆm a particularidade de serem constitu´ e ıdos por uma s´rie de objectos logicamente encadeados, conhecie dos por sinks, que aceitam mensagens, isto ´, objectos do e tipo IMessage, de um elemento anterior, efectuam alguma opera¸˜o sobre estas e submetem-nas ao pr´ximo elemento ca o da cadeia de sinks.

mensagens atrav´s do canal. Entre outros, poderia ser dee senvolvido um sink para a encripta¸˜o de mensagens, outro ca que guardasse um log de todas as mensagens trocadas entre os objectos, ou ainda outro que exigisse algum tipo de autentica¸˜o adicional por parte dos clientes envolvidos [4]. ca O desenvolvimento de novos formatters passa pela implementa¸˜o do tipo ISerializable, que cont´m apenas o ca e m´todo GetObjectData(). Este m´todo ´ chamado quando e e e ´ necess´rio serializar o objecto. Quando est˜o envolvie a a dos tipos n˜o suportados por este m´todo (por exemplo, a e referˆncias), a plataforma recorre a surrogates e surrogate e selectors.

2.2.4

Activacao ¸˜

Figura 7: Transforma¸˜es de uma mensagem atrav´s co e de um canal e da sua cadeia de sinks. Um dos elementos mais importantes, e normalmente o primeiro nesta cadeia de objectos, ´ o formatter sink, ree spons´vel pela serializa¸˜o da mensagem propriamente dita, a ca preparando-a assim para ser transmitida pelo canal. Os elementos interm´dios podem efectuar processamento adicional e sobre esta, sendo que o ultimo elemento da cadeia fica ent˜o ´ a 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 objecto do tipo SoapFormatter, enquanto que o TcpChannel utiliza um BinaryFormatter. Como j´ foi mencionado, todos estes componentes poa dem ser extendidos. Em particular, podem ser introduzidos novos elementos na cadeia de sinks, substitu´ ıdos ou removidos outros, de forma a manipular o processamento das 5

A plataforma suporta a activa¸˜o de objectos remotos a ca partir dos cliente ou do pr´prio servidor. A activa¸˜o por o ca parte do servidor ´ normalmente utilizada quando os objece tos envolvidos n˜o tˆm necessidade de manter o seu estado a e entre diferentes opera¸˜es, enquanto que, por outro lado, a co activa¸˜o a partir do cliente resulta numa instancia¸˜o do ca ca objecto remoto a pedido do cliente, sendo a sua gest˜o do a tempo de vida feita atrav´s de um sistema de leases. e Assim, os objectos activados no servidor s˜o geridos por a este, sendo instanciados apenas quando ocorre a primeira invoca¸˜o por parte de um cliente. Este tipo de objectos ca apenas suporta construtores sem parˆmetros e tˆm a sua a e localiza¸˜o bem definida e conhecida, uma vez que est˜o ca a associados a um URI. Podem ser de dois tipos distintos: Singleton ou SingleCall. Os objectos do tipo Singleton baseam-se no padr˜o de a desenho com o mesmo nome e portanto dizem respeito a tipos de objectos que s˜o instanciados uma unica vez e com a ´ um unico ponto global de acesso durante o seu per´ ´ ıodo de execu¸˜o [3]. Tal como os restantes tipos de objectos remoca tos, estes tamb´m tˆm um tempo de vida pr´-determinado, e e e o que significa que os seus clientes n˜o obter˜o necessaria a amente sempre uma referˆncia para a mesma instˆncia da e a classe remota. Este aspecto tem implica¸˜es na gest˜o do co a estado destes objectos e pode ser contornado, for¸ando a c manuten¸˜o do objecto em mem´ria, enquanto o dom´ ca o ınio aplicacional do servidor estiver em execu¸˜o, atrav´s de uma ca e lease nula. Assim, ´ poss´ que este objecto mantenha um e ıvel determinado estado entre invoca¸˜es e que este seja modco ificado ou obtido por diferentes clientes. No entanto, este tipo de interac¸˜o com objectos Singleton deve ser efectuca ada com alguma precau¸˜o, uma vez que o seu acesso n˜o ca a ´ sincronizado, podendo servir dois clientes concorrentes em e threads de execu¸˜o diferentes. ca Os tipos remotos SingleCall tˆm sempre uma instˆncia e a por pedido, de modo que cada invoca¸˜o por parte de um ca cliente ´ servida por uma instˆncia diferente, com um estado e a distinto. Os objectos activados pelos clientes s˜o instanciados a a partir do momento em que este cria um novo objecto do tipo remoto pretendido, com o operador new ou com o m´todo e Activator.CreateInstance(). Neste cen´rio, o cliente pode a participar na gest˜o da vida do objecto remoto, utilizando a as j´ mencionadas leases. Tamb´m possibilita a instana e cia¸˜o parametrizada bem como a manuten¸˜o do estado ca ca do objecto por cliente, uma vez que cada cliente tem a sua instˆncia distinta do objecto remoto em execu¸˜o no servia ca dor.

2.3

Heterogeneidade

2.5

Gest˜ o do Ciclo de Vida a

A plataforma em estudo resolve de forma elegante e eficaz os problemas associados ` heterogeneidade, normalmente a discutidos nos sistemas de objectos distribu´ ıdos.

2.3.1

Linguagens de Programacao ¸˜

A existˆncia de um sistema de tipos comum, que garante e a interoperabilidade e integra¸˜o dos tipos, atrav´s da imca e posi¸˜o de regras e especifica¸˜o de um modelo de objectos ca ca comum, resolve o problema da utiliza¸˜o de v´rias linguaca a gens de programa¸˜o no processo de desenvolvimento. ca Todo o c´digo produzido por uma linguagem que esteja eso pecificada de acordo com o Common Type System ´ traduzido e para uma linguagem interm´dia comum, que mais tarde ´ e e interpretada pelo runtime e transformada em c´digo nativo. o

Nesta plataforma, a problem´tica relativa ` gest˜o do ciclo a a a de vida dos objectos ´ solucionada com recurso ` utiliza¸˜o e a ca de leases e sponsorships que, uma vez associadas aos objectos remotos, evitam que estes sejam recolhidos pelo mecanismo local de recolha de lixo. A excep¸˜o a este cen´rio ca a reside nos objectos single-call activados no servidor, que s˜o a desactivados imediatamente ap´s uma invoca¸˜o sobre as o ca suas opera¸˜es. co

2.5.1

Leases e Sponsors

2.3.2

Representacao dos dados ¸˜

Uma vez que o c´digo nativo ´ executado em runtimes deo e vidamente condicionados e baseados na mesma implementa¸˜o, ca a heterogeneidade na representa¸˜o dos dados n˜o ´ um ca a e problema, desde que o ambiente de execu¸˜o seja comum, ca isto ´, tenha como base a mesma vers˜o de uma determinada e a implementa¸˜o da CLI. ca A utiliza¸˜o de diferentes implementa¸˜es e vers˜es de ca co o uma ou mais CLI’s n˜o garante a representa¸˜o homog´nea a ca e dos dados, uma vez que a estrutura interna dos tipos pode ter sido alterada, tornando-as efectivamente incompat´ ıveis.

2.4

Localizacao ¸˜

A designa¸˜o de servi¸os remotos na plataforma consiste ca c na atribui¸˜o de URIs bem conhecidos aos objectos e s˜o ca a definidos na fase em que estes s˜o registados na plataforma. a O registo de objectos ´ normalmente realizado pela aplica¸˜o e ca que os instancia, registando os canais de comunica¸˜o atrav´s ca e de opera¸˜es disponibilizadas pela classe ChannelServices e co os objectos remotos atrav´s da classe RemotingConfiguration. e O registo de um objecto remoto s´ ´ poss´ o e ıvel mediante a seguinte informa¸ao: c˜ 1. o nome do tipo do objecto remoto. 2. o URI que o designa. 3. o tipo de activa¸˜o. ca No caso dos objectos activados pelo servidor, esse URI ´ e fixo e conhecido, enquanto que nos objectos activados pelos clientes, esse URI ´ gerado e relativo a uma instˆncia e a particular do tipo de objecto no servidor. // registo de um canal de comunica¸~o ca TcpChannel channel = new TcpChannel(4321); ChannelServices.RegisterChannel(channel); // registo do tipo de objecto remoto RemotingConfiguration.RegisterWellKnownServiceType( typeof(MyRemoteObject), "MyRemoteObjectUri", WellKnownObjectMode.Singleton ); Figura 8: Registo t´ ıpico de um objecto remoto.

Tal como os restantes sistemas de objectos distribu´ ıdos, em .NET Remoting a gest˜o de ciclo de vida est´ associada a a ao mecanismo de recolha de lixo, que mant´m informa¸˜o e ca acerca dos objectos em utiliza¸˜o pelos clientes. Quando ca um objecto deixa de ser referenciado pelos clientes, ´ recole hido e eventualmente destru´ ıdo, sendo libertada a mem´ria o anteriormente atribu´ ıda. Este processo ´ eficaz num cen´rio onde as aplica¸˜es pare a co tilham o mesmo processo de execu¸˜o (a mesma CLR). Num ca cen´rio distribu´ a ıdo, a situa¸˜o ´ diferente, uma vez que um ca e objecto pode n˜o ter clientes locais, mas sim clientes que a est˜o em execu¸˜o em processos e m´quinas diferentes, onde a ca a a recolha prematura de um objecto resultaria na invalida¸˜o ca da referˆncia remota possu´ pelos clientes. e ıda A solu¸˜o implementada na plataforma .NET envolve a ca utiliza¸˜o de leases e funciona da seguinte forma: o acesso ca a um objecto no servidor por parte de um cliente resulta na associa¸˜o deste a um objecto lease, que mantˆm, entre ca e outras propriedades, um per´ ıodo de tempo durante o qual o objecto servidor n˜o dever´ ser recolhido. O lease mana a ager, respons´vel pela gest˜o das associa¸˜es entre objectos a a co e leases, d´ in´ ` contagem decrescente do tempo de lease a ıcio a a partir do momento em que a primeira referˆncia ´ envie e ada para fora do seu dom´ ınio de execu¸˜o. Esta entidade ca tamb´m mant´m uma referˆncia para o objecto servidor, e e e evitando assim a sua recolha para destrui¸˜o. Uma vez exca pirada a lease de um objecto, a CLR assume que n˜o existem a clientes a utilizar referˆncias remotas e descarta tamb´m a e e sua referˆncia local [6]. e No entanto, n˜o s˜o dadas garantias de que n˜o exisa a a tam ainda clientes que possuam referˆncias para os objece ´ tos remotos. E ent˜o necess´rio providenciar uma forma de a a estes poderem extender as leases. Aqueles clientes que precisam de ser contactados quando o tempo de vida de um objecto remoto termina devem recorrer a um objecto sponsor, registando-o na lease respectiva. Assim, o gestor de leases percorre a lista de sponsors associada ` lease do oba jecto em quest˜o e identifica se h´ ou n˜o necessidade de a a a extender o seu tempo de vida.

2.5.2

Propriedades das Leases

Uma lease ´ instanciada com valores atribu´ e ıdos por omiss˜o a a `s suas propriedades (ver Figura 9), mas que podem ser alterados antes de serem registados os objectos no servidor, quer programaticamente, quer atrav´s dos ficheiros de cone figura¸˜o da aplica¸˜o. ca ca A propriedade RenewOnCallTime tem um valor de tempo adicional que ´ automaticamente acrescentado ao tempo de e vida do objecto caso sejam invocados m´todos sobre este, e perto da expira¸˜o da sua lease. Esta renova¸˜o do tempo ca ca de lease s´ ´ efectuada caso o restante tempo de vida do o e objecto seja inferior ao valor atribu´ ` propriedade anteriıdo a 6

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 progressivamente o seu tempo de vida. A propriedade LeaseManagerPollTime indica a dura¸˜o ca do intervalo de tempo que dever´ decorrer entre a verifica¸˜o a ca dos tempos das leases, que por omiss˜o ´ de 10 segundos, a e enquanto que a propriedade SponsorshipTimeout especifica o tempo que o servidor dever´ esperar por respostas dos a clientes remotos quando inquire estes acerca do estado da sua sponsorship. Esta propriedade ´ importante pois ´ a e e partir deste valor que s˜o toleradas falhas de comunica¸˜o a ca com os clientes, sendo estes removidos da lista de sponsors da lease caso n˜o respondam dentro do intervalo de tempo a estabelecido. Um objecto remoto pode tamb´m alterar as propriedades e do seu ciclo de vida ap´s a sua instancia¸˜o, fornecendo uma o ca implementa¸˜o para o m´todo InitializeLifetimeService ca e e devolvendo um objecto do tipo ILease.

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

2.7

Interoperabilidade

A interoperabilidade da plataforma .NET Remoting em rela¸˜o a outros sistemas de objectos distribu´ ca ıdos assenta sobretudo no protocolo SOAP e no mecanismo de pedidos de invoca¸˜es remotas facultado, expressos sob a forma co de mensagens SOAP. Este protocolo especifica um formato XML normalizado, que permite a inclus˜o de defini¸˜es de a co tipos e dados estruturados, independente da plataforma e linguagem de programa¸˜o utilizadas. Esta possibilidade de ca oferecer servi¸os web, baseados em XML, a clientes potenc cialmente desenvolvidos sobre outras plataformas e arquitecturas, garante que as mensagens podem ser trocadas e entendidas entre sistemas diferentes, escondendo assim os detalhes de implementa¸˜o dos servi¸os remotos. ca c

2.8

Configurabilidade

De forma a introduzir alguma flexibilidade na configura¸˜o ca dos servi¸os oferecidos pelos objectos remotos, a plataforma c suporta o carregamento de determinadas propriedades a partir de ficheiros, sem ser necess´rio recompilar o c´digo. a o ´ E poss´ ıvel ent˜o especificar num ficheiro de configura¸˜o a ca a porta e o tipo de canal utilizado no estabelecimento de liga¸˜es ao objecto remoto, o seu modelo de activa¸˜o, o co ca 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¸˜o ca

2.5.3

Sponsors

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

2.9

Ambientes de Execucao ¸˜

2.6

Persistˆ ncia e

O suporte ao armazenamento de tipos de objectos num reposit´rio de dados persistente n˜o constitui um servi¸o ino a c trinsecamente ligado ao .NET Remoting, mas est´ presente a na plataforma .NET como um componente gen´rico para o e 7

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

j´ existentes: o IIS (Internet Information Services) ou aos a servi¸os COM+. c

2.9.1

Integracao no IIS ¸˜

O IIS ´ um servidor web e normalmente est´ sempre em e a execu¸˜o num ambiente Windows. Como tal, presta-se a ser ca um bom anfitri˜o aos componentes remotos que se querem a disponibilizar, apesar de estar limitado ` utiliza¸˜o de canais a ca HttpChannel. Por outro lado, possibilita uma configura¸˜o ca r´pida das restri¸˜es de seguran¸a impostas aos componentes a co c e a altera¸˜o da sua configura¸˜o sem ser necess´rio reca ca a iniciar o servi¸o. c

2.9.2

Integracao nos servicos COM+ ¸˜ ¸

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

a interoperabilidade entre objectos desenvolvidos em diferentes linguagens, possibilitando a execu¸˜o e comunica¸˜o ca ca entre estes num ambiente CLI, onde o tratamento de erros estabelecido segue um modelo at-most-once. A utiliza¸˜o de proxys como mecanismo de atingir um ca modelo de transparˆncia de acesso ´ comum a todos os sise e temas referidos, sendo de real¸ar que em Remoting, a cria¸˜o c ca e manipula¸˜o dos objectos deste tipo ´ completamente inca e vis´ para o utilizador ou programador. ıvel O mecanismo de leases constitui o modelo de recolha de objectos para os quais j´ n˜o existem referˆncias e est˜o a a e a tamb´m implementadas variadas formas de suporte ` ace a tiva¸˜o dinˆmica dos objectos servidores. ca a Em suma, a infra-estrutura de Remoting tem bastantas semelhan¸as com a do Java/RMI, mas oferece de raiz, em c determinados aspectos, mais funcionalidades associadas ao tratamento dos objectos remotos, e na configura¸˜o e exca tens˜o dos canais de comunica¸˜o. A interoperabilidade com a ca outras plataformas atrav´s de protocolos como o SOAP e e HTTP evidencia tamb´m uma abertura para a integra¸˜o e ca entre sistemas com diferentes implementa¸˜es. co

5.

REFERÊNCIAS

3.

EXEMPLOS

Procedeu-se ao desenvolvimento de um conjunto de exemplos simples, demonstrativos das funcionalidades disponibilizadas pelo infra-estrutura de Remoting, sobre uma implementa¸˜o da CLI open source e compat´ ca ıvel com sistemas UNIX, designada por Mono e dispon´ em http://www.monoıvel project.com/. Esta distribui¸˜o implementa toda a funcionalidade da ca vers˜o 1.1 da plataforma .NET dispon´ para sistemas opa ıvel erativos Microsoft Windows e ainda extende a distribui¸˜o ca ´ base com uma s´rie de m´dulos adicionais. E composta e o por uma m´quina virtual, que constitui o ambiente cona trolado de execu¸ao das aplica¸˜es, um compilador just-inc˜ co time, para a linguagem interm´dia, uma API que reproduz e as Framework Class Libraries da Microsoft e um compilador de C#. S˜o apresentadas, no apˆndice deste documento, listagens a e de alguns dos exemplos desenvolvidos, sendo que os restantes estar˜o dispon´ a ıveis num ficheiro que dever´ acompanhar este a trabalho.

[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¸˜es de alguns exco emplos desenvolvidos no ˆmbito de uma demonstra¸˜o das a ca capacidades da plataforma .NET Remoting, conforme detalhadas no texto.

4.

˜ CONCLUSOES

A infra-estrutura de Remoting, integrada na plataforma .NET, apresenta caracter´ ısticas comuns a outros sistemas de objectos distribu´ ıdos, n˜o alheio ao facto de esta ter sido a a abordagem mais recente ao suporte de invoca¸˜es em objecco tos remotos e toda a problem´tica em redor. a Tal como o CORBA, DCOM e Java/RMI, em Remoting ´ poss´ solicitar a execu¸˜o de opera¸˜es em objectos rese ıvel ca co identes noutros contextos de execu¸˜o, num ambiente disca ` tribu´ ıdo. A semelhan¸a do Java/RMI, a inclus˜o no modelo c a de objectos de objectos n˜o-remotos exige uma diferencia¸˜o a ca no seu tratamento a n´ ıvel de tipos, e, como nos sistemas acima mencionados, todo o objecto remoto ´ identificado a e partir de uma referˆncia que assegura a transparˆncia de e e localiza¸˜o. ca A Common Type System estabelece a separa¸˜o entre a ca no¸˜o de interfaces e implementa¸˜es, e define regras para ca co 8

A.1
A.1.1

Hello World - Client Activated
RemoteObject.cs

using System; using System.Runtime.Remoting; namespace com.mgcm.net.remoting { public class RemoteObject : MarshalByRefObject { public RemoteObject() { } public string HelloWorld()

{ return "Hello World!"; } } }

using using using using

System; System.Runtime.Remoting; System.Runtime.Remoting.Channels; System.Runtime.Remoting.Channels.Tcp;

A.1.2
using using using using

RemoteServer.cs
System; System.Runtime.Remoting; System.Runtime.Remoting.Channels; 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.GetObject( typeof(com.mgcm.net.remoting.RemoteObject), "tcp://localhost:8080/HelloWorld"); Console.WriteLine(obj.HelloWorld()); return 0; }

namespace com.mgcm.net.remoting { public class RemoteServer { public static int Main(string[] args) { TcpChannel tcp = new TcpChannel(8080); ChannelServices.RegisterChannel(tcp); RemotingConfiguration.RegisterWellKnownServiceType( } } typeof(RemoteObject), "HelloWorld", A.3 WellKnownObjectMode.SingleCall); System.Console.WriteLine("server running..."); System.Console.ReadLine(); return 0; } } }

Execucao de C´ digo M´ vel ¸˜ o o
Interfaces.cs

A.3.1

A.1.3
using using using using

RemoteClient.cs
System; System.Runtime.Remoting; System.Runtime.Remoting.Channels; System.Runtime.Remoting.Channels.Tcp;

namespace com.mgcm.net.remoting { public interface ITask { void exec(); } public interface IAgent { void run(); } public interface IAgentHost { void accept(IAgent agent); } }

namespace com.mgcm.net.remoting { public class RemoteClient { public static int Main(string[] args) { TcpChannel tcp = new TcpChannel(); ChannelServices.RegisterChannel(tcp);

A.3.2

Tasks.cs

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() } { } } }

A.2
A.2.1

Hello World - Server Activated
RemoteClient.cs
9

public void exec() { System.Console.WriteLine("Hello World"); }

} [Serializable] public class TaskDateNow: ITask { public TaskDateNow():base() { } public void exec() { System.Console.WriteLine(DateTime.Now); } } }

A.3.4

Agent.cs

using System; namespace com.mgcm.net.remoting { [Serializable] public class Agent: IAgent { private ITask task; public Agent(ITask task) { this.task = task; } public void run() { task.exec(); } } }

A.3.3
using using using using using using

AgentHost.cs
System; System.Runtime.Remoting; System.Runtime.Remoting.Channels; System.Runtime.Remoting.Channels.Tcp; System.Collections; System.Threading;

A.3.5
using using using using

Server.cs
System; System.Runtime.Remoting; System.Runtime.Remoting.Channels; System.Runtime.Remoting.Channels.Tcp;

namespace com.mgcm.net.remoting { public class AgentHost: MarshalByRefObject, IAgentHost { private Stack agents; public AgentHost() { agents = new Stack(); Thread t = new Thread( new ThreadStart(execAgents) ); t.Start(); } public void accept(IAgent agent) { agents.Push(agent); } public void execAgents() { while (true) { if (agents.Count > 0) { IAgent agent = (IAgent) agents.Pop(); Thread t = new Thread( new ThreadStart(agent.run) ); t.Start(); } System.Threading.Thread.Sleep(500); } } } }

namespace com.mgcm.net.remoting { public class Server { public static void Main(string[] args) { int port = 8080; TcpChannel channel = new TcpChannel(port) ChannelServices.RegisterChannel(channel); RemotingConfiguration.RegisterWellKnownServiceType( typeof(AgentHost), "AgentHost", WellKnownObjectMode.Singleton ); System.Console.ReadLine(); } } }

A.3.6
using using using using

Client.cs
System; System.Runtime.Remoting; System.Runtime.Remoting.Channels; System.Runtime.Remoting.Channels.Tcp;

namespace com.mgcm.net.remoting { 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 = ITask task2 = IAgent agent1 IAgent agent2 new TaskHello(); new TaskDateNow(); = new Agent(task1); = new Agent(task2);

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

11