Rmi

Pessoal bom dia,

Desenvolvi uma aplicação utilizando RMI e fiz a conexão na porta 4262, até aí tudo bem. O problema e que o meu cliente funciona em um escritorio em outra cidade atraves de VPN e nás duas estremidades possui um firewall, quando conecto o cliente ao servidor tudo bem, foi so liberar a porta citada que funcionou, porem quando tento utilizar qualquer metodo remoto não funciona, aí o administrador da rede verificou que a aplicação estava solicitando outra porta alem da 4262. Foi só liberar esta nova porta que funcionou.

Gostaria de saber porque que a aplicação precisa de outra porta para funcionar, se a conexão é estabelecida na porta 4262. E é utilizada uma outra porta, como faço para definir esta porta em meu código, pois toda vez que paro o servidor para alguma atualização, esta porta muda e tenho que procurar o administrador da rede para analizar a rede e verificar qual a porta que a aplicação está requisitando para que esta possa ser liberada.

Aguardo retorno e dede já agradeço pela atenção.

Ola,

Vc consegue definir estas portas na hora de exportar os serviços RMI, em geral toda classe seua que é um serviço, implementa uma interface que extendeu de Remote e extends de UnicastRemoteObject, neste UnicastRemoteObject tem alguns construtores… e um deles é o que toma o numero da porta como parametro, só vc usar este.

BLZ,

A porta 4262 está definida no construtor. Porem quando solicito algum método remoto e comunicação é feita em outra porta. Segue abaixo o codigo onde a porta é configurada.

[
try
{
inter = (InterfaceDeAcesso) Naming.lookup(“rmi://192.168.18.4:4262/CONTROLEAUTORIZACAO”);
}
catch(Exception e)
{
System.exit(0);
}
]

O RMI utiliza uma porta somente para o RMI Registry, e uma para cada stub regitrado nele, a qual será a porta que o stub irá escutar. Se você criar o stub utilizando o método UnicastRemoteObject.exportObject(Remote objetoRemoto), este seu objetoRemoto irá escutar em uma porta anônima (aleatória), sendo assim vocÊ não irá saber que porta deve liberar no firewall. Agora, criando o stub utilizando o método UnicastRemoteObject.exportObject(Remote objetoRemoto,int porta), seu stub irá escutar na porta especificada, assim basta você liberar esta porta e a porta do RMI Registry no seu firewall. Vale lembrar que a porta que você especificar para o stub não pode ser 0 (zero), pois se for seu stab irá escutar em uma porta aleatória, ou seja UnicastRemoteObject.exportObject(Remote objetoRemoto) é igual a UnicastRemoteObject.exportObject(Remote objetoRemoto, 0).

Esta porta que vocÊ passa no lookup é a porta do RMIRegistry, e não a porta em que seu serviço irá escutar

Andrey,

Da forma que desenvolvi a aplicação usando Naming.rebind("",obj) ao invés de UnicastRemoteObject.exportObject(Remote objetoRemoto,int porta), é possivel setar a porta que o serviço irá escutar, ou tenho que mudar a aplicação. Estou tentando mudar más estou apanhando um pouco.

A alteração que você tem que fazer é quando você cria o stub, antes de fazer o rebind. Você deve ter feito algo assim:

[code]
//Cria o Stub
Remote stub = UnicastRemoteObject.exportObject(objetoRemoto);

//Publica o stub
Naming.rebind(“rmi://endereco/do/stub”, stub);[/code]
A alteração que você deve fazer é na linha 2, adicionando a porta que você quer para stub no exportObject:

Remote stub = UnicastRemoteObject.exportObject(objetoRemoto, porta);

Manda aí o código em que você publica o objeto no rmiregistry q acho q fica melhor de te explicar

Bem, na verdade meu servidor está desta forma,

try
{
   InterfaceImpl horasImpl = new InterfaceImpl();    
   
   Naming.rebind("rmi://localhost:4262/CONTROLEAUTORIZACAO", horasImpl );

}  catch(Exception e){e.printStackTrace();}

Onde InterfaceImpl é minha classe com os métodos implementados, esta classe herda os métodos de uma outra classe chamada InterfaceDeAcesso que está tanto no cliente como no servidor.

Tentei mudar meu código para

try
{
   InterfaceImpl horasImpl = new InterfaceImpl();  
   
   Remote stubServidor = UnicastRemoteObject.exportObject(horasImpl,2579);   
               
   Registry registry = LocateRegistry.getRegistry(4262);   
    
   registry.bind("rmi://localhost/CONTROLEAUTORIZACAO", stubServidor);  
   
}  catch(Exception e){e.printStackTrace();}

Porem quando executo o servidor é mostrado o seguinte erro.

java.rmi.server.ExportException: object already exported
at sun.rmi.transport.ObjectTable.putTarget(ObjectTable.java:172)
at sun.rmi.transport.Transport.exportObject(Transport.java:74)
at sun.rmi.transport.tcp.TCPTransport.exportObject(TCPTransport.java:229)
at sun.rmi.transport.tcp.TCPEndpoint.exportObject(TCPEndpoint.java:393)
at sun.rmi.transport.LiveRef.exportObject(LiveRef.java:129)
at sun.rmi.server.UnicastServerRef.exportObject(UnicastServerRef.java:190)

Estou enviando o código da minha aplicação (Servidor), para que você possa me ajudar.

import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
import java.io.*;

public interface InterfaceDeAcesso extends Remote
{ 
 public String verificarusuario(String usuario, String senha) throws RemoteException;
}
import java.rmi.*;
import java.rmi.server.*;
import java.text.*;
import java.util.*;
import java.io.*;

public class InterfaceImpl extends UnicastRemoteObject implements InterfaceDeAcesso
{  
 Date data = new Date();
 DateFormat formatoData = new SimpleDateFormat("dd/MM/yyyy");
 DateFormat formatoHora = DateFormat.getTimeInstance();
 DateFormat formatoDiaSemana = new SimpleDateFormat("EEEE");
 
 BancoDados base; 
    
 public InterfaceImpl() throws RemoteException
 {    
  base = new BancoDados(); 

  base.defineDriver("org.firebirdsql.jdbc.FBDriver");
  base.defineEndereco("jdbc:firebirdsql:192.168.18.4/3050:c:/Programas/ControleDeAutorizacoes.gdb"); 
  base.defineUsuario("SYSDBA");
  base.defineSenha("masterkey");
 }        
    
 public String verificarusuario(String usuario, String senha) throws RemoteException
 {
  String localAtendimento = "";
  
  base.abreConexao();
  
  comandoSQL = "SELECT localAtendimento FROM Usuario WHERE nome = '" + usuario + "' AND senha = '" + senha + "'";
  base.executaConsulta(comandoSQL);
  
  while(base.proximoRegistro())
   localAtendimento = base.retornaString("localAtendimento");
  
  base.fechaConexao();
  
  return localAtendimento;
 }
}
import java.rmi.*;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.*;

public class Servidor
{
 public Servidor() 
 {
  try
  {
    InterfaceImpl horasImpl = new InterfaceImpl();  
    Naming.rebind("rmi://localhost:4262/CONTROLEAUTORIZACAO", horasImpl );  
  }
  catch(Exception e){System.out.println("Erro !");e.printStackTrace();}     
 }    
 
 public static void main(String args[]) 
 {
  java.awt.EventQueue.invokeLater(new Runnable() 
  {
   public void run() 
   {
    new Servidor();
   }
  });
 }
}

Este erro aconteceu porque você já tinha exportado um objeto com o nome “CONTROLEAUTORIZACAO”.
Tente reiniciar o RmiRegistry.
Para garantir que isto nao vai mais acontecer, use Naming.rebind em vez de Naming.bind

Bom, agora funcionou, depois de uma boa surra.
O erros estavam acontecendo porque minha classe InterfaceImpl Herdava de UnicastRemoteObject, e quando tentava exportar o objeto com o comando que você me passou dava aquele erro, foi só tirar a herança que tudo funcionou. Já fiz o teste no escritório na outra cidade. Agora não terei mais problemas com as portas.

Muito obrigado pela ajuda.