Desenvolvendo uma aplicação CORBA
utilizando C#
Tecgraf PUC-Rio
Novembro de 2013
versão 1 - julho/2013
Exemplo passo-a-passo
• Veremos um exemplo, passo-a-passo, de
desenvolvimento de aplicações CORBA
usando C#
• Para desenvolver a aplicação, usaremos o
IIOP.NET como ORB tanto para o cliente
quanto para o servidor, já que ambos serão
desenvolvidos em C#
versão 1 - julho/2013
Passo 1: IIOP.NET e .NET
• Para o OpenBus, precisaremos de uma versão
alterada do IIOP.NET, com algumas correções
e novas funcionalidades. Essa versão pode ser
obtida:
• Do pacote do exercício, no site do curso
• Dos pacotes mais recentes do OpenBus ou SCS, em
seus respectivos sites
• Precisaremos também do .NET Framework 4.0
• Para compilar o exemplo, usaremos o Visual
Studio 2010
versão 1 - julho/2013
Libs do Pacote do Exercício
• Para o seu programa:
• IIOPChannel.dll
• Para o compilador de IDL:
• IIOPChannel.dll
• IDLPreprocessor.dll
versão 1 - julho/2013
Passo 2: Escrevendo a IDL
// StockMarket.idl
// O módulo StockMarket consiste das definições
// úteis para desenvolvimento de aplicações
// que lidam com mercado de ações.
module StockMarket {
// Exceção para definir o uso de um símbolo desconhecido
exception UnknownSymbol {
string symbol;
};
// O tipo StockSymbol é usado para representar os
// identificadores das ações
typedef string StockSymbol;
// Um StockSymbolList é uma sequência de StockSymbols.
typedef sequence<StockSymbol> StockSymbolList;
// A interface StockServer é a interface que fornece
// as informações sobre as ações do mercado.
interface StockServer {
// getStockValue() retorna o valor de uma
// determinada ação identificada por um
// StockSymbol fornecido como parâmetro de entrada.
// Se o StockSymbol dado for desconhecido, a exceção
// UnknownSymbol deve ser lançada.
float getStockValue(in StockSymbol symbol);
};
};
// getStockSymbols() retorna uma sequência com todos os
// StockSymbols conhecidos pelo servidor do mercado de
// ações.
StockSymbolList getStockSymbols();
versão 1 - julho/2013
Passo 3: Compilando a IDL
• Para compilar a IDL, usaremos o compilador IDL do
IIOP.NET:
IDLToCLSCompiler.exe -asmVersion 1.0.0
StockMarket.Idl StockMarket.idl
• Todas as classes estarão dentro da biblioteca
StockMarket.Idl.dll
• Para essa idl apenas a interface StockServer será
gerada
• Caso existam ValueTypes na idl, pode-se passar a
opção –vtSkel para que esqueletos sejam gerados
automaticamente
versão 1 - julho/2013
Interface Files
• A interface IDL StockServer é mapeada para:
– uma interface C# de assinatura StockServer
• A interface de assinatura possui o mesmo nome da
interface IDL, estende outras interfaces CORBA e é
usada como o tipo referenciado em outras interfaces
versão 1 - julho/2013
StockServer.cs
// Type: StockMarket.StockServer
// Assembly: StockMarket.Idl, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// Assembly location: StockMarket.Idl.dll
using Ch.Elca.Iiop.Idl;
namespace StockMarket
{
[RepositoryID("IDL:StockMarket/StockServer:1.0")]
[InterfaceType(IdlTypeInterface.ConcreteInterface)]
public interface StockServer : IIdlEntity
{
[FromIdlName("getStockValue")]
float getStockValue([StringValue, WideChar(false)] string symbol);
[FromIdlName("getStockSymbols")]
[return: IdlSequence(0L)]
[return: WideChar(false)]
[return: StringValue]
string[] getStockSymbols();
}
}
Ch.Elca.Iiop.Idl.IDLEntity: interface de “marcação” cuja finalidade é apenas
indicar que a classe que implementa essa interface é um tipo IDL
versão 1 - julho/2013
Classes de apoio do IIOP.NET
• O IIOP.NET permite apenas uma instância de
ORB, e essa instância é um singleton
OrbServices orb = OrbServices.GetSingleton();
• A classe OrbServices oferece diversas
funcionalidades devido à fuga do padrão CORBA:
– Funcionalidades do ORB
– Incluindo criação de tipos IDL para inserção em any
– Métodos que estariam no CORBA::Object
– _is_a(), _non_existent()
– Métodos relacionados à interceptação
versão 1 - julho/2013
Classes de apoio do IIOP.NET
• A classe ChannelServices oferece
funcionalidades para:
– Registro de canais de comunicação
– URLs de objetos (URLs são object ids de CORBA)
• Para enviar ou receber chamadas, é
necessário estabelecer um canal de
comunicação
• Servidores devem especificar uma porta (0 para
aleatória)
IiopChannel chan = new IiopChannel(0);
ChannelServices.RegisterChannel(chan, false);
versão 1 - julho/2013
Classes de apoio do IIOP.NET
• O IIOP.NET não implementa o conceito de
POA para o usuário
• Mas permite a configuração de algumas políticas (FAQ)
• Para registrar um servant, deve-se utilizar:
RemotingServices.Marshal(servant);
• Existe um método análogo, Unmarshal
• Essa classe possui alguns outros métodos
estáticos com funcionalidades que seriam do
POA
versão 1 - julho/2013
Classes de apoio do IIOP.NET
• A classe Ch.Elca.Iiop.Idl.Repository
oferece funcionalidades relacionadas ao
repositório de interfaces, como a obtenção
do RepositoryId de um tipo idl:
Ch.Elca.Iiop.Idl.Repository.GetRepositoryID(typeof (Node));
• Não existe um método narrow; o typecast
deve ser feito como em typecasts C# comuns
versão 1 - julho/2013
Passo 4: Compilando o código C#
• Para compilar seu código, adicione a
biblioteca com os símbolos gerados a partir
da idl como dependência
(StockMarket.Idl.dll)
• Adicione também a biblioteca do IIOP.NET
(IIOPChannel.dll)
• Você deve utilizar a mesma versão que foi
utilizada pelo compilador IDL
versão 1 - julho/2013
Passo 5: Implementando o Servant
• O servant que implementa a interface definida
na IDL StockServer deve ser uma classe que:
• Implemente a interface C# StockServer
• Estenda a classe abstrata MarshalByRefObject
• O nome do servant pode ser qualquer um; por
exemplo, StockServerImpl
versão 1 - julho/2013
Tempo de Vida do Servant
• Para que seu servant não seja coletado em um
momento indefinido você deve fornecer uma
política de tempo de vida, sobrescrevendo o método
InitializeLifetimeService(). Para que ele nunca
seja coletado, basta retornar null
public override object InitializeLifetimeService() {
return null;
}
versão 1 - julho/2013
Exemplo de Implementação
using System;
using System.Collections.Generic;
namespace StockMarket {
public class StockServerImpl : MarshalByRefObject, StockServer {
// neste exemplo só há leituras no mapa, então não precisamos
// nos preocupar com concorrência
private readonly IDictionary<string, float> _myStock;
private readonly string[] _symbols;
public StockServerImpl() {
_myStock = new Dictionary<string, float>();
//Inicializa as ações com nomes e valores
// fixos ou atribuídos randomicamente
...
_symbols = new string[_myStock.Count];
_myStock.Keys.CopyTo(_symbols, 0);
}
public float getStockValue(string symbol) {
float value;
_myStock.TryGetValue(symbol, out value);
return value;
}
public string[] getStockSymbols() {
return _symbols;
}
}
}
versão 1 - julho/2013
Passo 6: Implementando o servidor
• O programa servidor se encarrega de:
–
–
–
–
–
inicializar o ORB
criar o objeto Servant StockServerImpl
registrar o Servant no ORB
publicar sua referência
aguardar que o cliente envie requisições
• Para compilar o servidor, o compilador .NET
deve ter acesso à classe de interface e à classe
do Servant
versão 1 - julho/2013
Inicializa o ORB
• Não é necessário inicializar a única instância de
ORB
• É necessário estabelecer um canal de
comunicação
// Inicializa o ORB, indicando que utilize uma porta aleatória para receber chamadas
IiopChannel chan = new IiopChannel(0);
ChannelServices.RegisterChannel(chan, false);
versão 1 - julho/2013
Cria o Servant que implementa a IDL
StockServerImpl stockServer = new StockServerImpl();
versão 1 - julho/2013
Cria o Servant que implementa a IDL
• Note que, até aqui, temos apenas um objeto
C# instanciado, capaz de receber requisições
• Precisamos agora tornar esse objeto
conhecido pelo ORB, para que direcione
chamadas recebidas a ele
RemotingServices.Marshal(stockServer);
versão 1 - julho/2013
Publica a referência do objeto CORBA
• A interface omg.org.CORBA.ORB tem um
método para obter a referência de um
objeto CORBA em uma string
• Basta obter essa string a partir do singleton
do ORB, e em seguida publicá-la de alguma
forma (ex: arquivo)
ORB orb = OrbServices.GetSingleton();
string ior = orb.object_to_string(stockServer);
versão 1 - julho/2013
Bloqueia a thread corrente
Thread.Sleep(Timeout.Infinite);
• Bloqueia a thread corrente indefinidamente
versão 1 - julho/2013
Passo 7: Implementando o cliente
• O programa cliente se encarrega de:
– inicializar o ORB
– obter a referência para o objeto CORBA StockServer
– fazer chamadas aos métodos definidos pela IDL do
StockServer
• O compilador .NET deve ter acesso à classe de
interface gerada pelo compilador IDL
versão 1 - julho/2013
Exemplo do cliente do StockServer
namespace StockMarket {
internal static class StockMarketServer {
private static void Main(String[] args) {
// Inicializa o ORB
IiopClientChannel channel = new IiopClientChannel();
ChannelServices.RegisterChannel(channel, false);
// Lê o IOR do arquivo cujo nome é passado como parâmetro
string ior = File.ReadAllText(args[0]);
ORB orb = OrbServices.GetSingleton();
// Obtém a referência para o objeto CORBA
StockServer server = orb.string_to_object(ior) as StockServer;
if (server == null) {
Console.WriteLine("Arquivo de IOR com referência inválida.");
return;
}
// Executa chamadas ao objeto CORBA
. . .
}
}
}
versão 1 - julho/2013
Exemplo do cliente do StockServer
namespace StockMarket {
internal static class StockMarketServer {
private static void Main(String[] args) {
. . .
// Executa chamadas ao objeto CORBA
try {
Console.WriteLine("Ações obtidas do StockServer:");
// Obtém os símbolos de todas as ações:
string[] symbols = server.getStockSymbols();
// Mostra as ações com seus respectivos valores
foreach (string symbol in symbols) {
Console.WriteLine(symbol + " " + server.getStockValue(symbol));
}
}
catch (UnknownSymbol e) {
Console.WriteLine("O símbolo " + e.symbol + " não existe.");
}
catch (TRANSIENT) {
Console.WriteLine("O serviço encontra-se indisponível.");
}
catch (COMM_FAILURE) {
Console.WriteLine("Falha na comunicação com o serviço.");
}
}
}
}
versão 1 - julho/2013
Passo 8: Executando o servidor
Server.exe ior.txt
versão 1 - julho/2013
Saída da execução do servidor
Ações
UION:
LGBA:
ZZSP:
KLVV:
ZDZR:
UFTH:
DNKS:
AQVS:
AZHM:
PEMR:
criadas:
18.192759
46.23733
48.71345
57.355362
41.779728
74.87004
80.69647
99.87545
72.27951
35.293213
Servidor rodando.
versão 1 - julho/2013
Passo 9: Executando o cliente
Client.exe ior.txt
versão 1 - julho/2013
Saída da execução do cliente
Ações obtidas do StockServer:
UION 18.192759
LGBA 46.23733
ZZSP 48.71345
KLVV 57.355362
ZDZR 41.779728
UFTH 74.87004
DNKS 80.69647
AQVS 99.87545
AZHM 72.27951
PEMR 35.293213
versão 1 - julho/2013
Download

Compilando a IDL - Tecgraf JIRA / Confluence - PUC-Rio