RMI - Cliente/Servidor

19 respostas
N

Boa tarde Senhores.

Bom, dei uma pesquisada e infelizmente não encontrei a resposta para minha dúvida.
Eis a dúvida: estou finalizando um sistema P2P em RMI, claro, muito mais simples que os disponíveis no mercado, este é um sistema para a aplicação academica de RMI em Sistemas Distribuidos.
O que acontece é que em um sistema P2P, um cliente também é servidor, ou seja, você pode requisitar um arquivo para download como pode servir um arquivo para upload, já que a ideia do P2P é que os usuários possam trocar arquivos entre si (não é exatamente isso, mas a ideia é por ai…).

Imagine assim, o cliente clica em “Conectar”, neste momento ele tem o direito de efetuar um download mas também passa a ser um server para receber requisições, diante disso, eu gostaria de saber se é possível (creio que seja) o cliente iniciar seu próprio servidor via código, desta forma, toda a vez que um novo cliente conectar, ele passará a ser um novo cliente/servidor na rede.

Alguém teria uma sugestão e demonstração de como isso funcionaria?

Muito obrigado.
Desculpas, caso eu não tenha sido muito claro.

19 Respostas

M

se o que você quer é iniciar o servidor via código, no cliente, você consegue da seguinte forma:

//inicializa o registry rmi
LocateRegistry.createRegistry(1099);
//coloca o objeto no registro
Naming.rebind(url, objeto);

Perceba que eu coloquei em 2 tags code, execute estes 2 em duas threads diferentes, pois a primeira linha ai trava a thread, fazendo com que nada depois dessa linha execute na mesma (se fossem colocadas na mesma thread não seria adicionado o objeto nela).

no passado, eu com um projeto que usa RMI tive problema fazendo isso na hora de colocar o objeto no registro, tava mantendo o registro aberto quando eu fechava o software, e depois ao re-abrir tinha uns sockets abertos de antes de fechar da primeira vez... ai eu tinha uns BindException, que penso que você provavelmente também teria, sendo assim eu resolvi tirando o objeto do registro e colocando-o novamente.
try{
			MinhaInterfaceRMI obj = this;
			String rmiUrl = "rmi://localhost:1099/aplicacao";
			
			String[] servicos = Naming.list(rmiUrl);
			
			for (int i=0; i<servicos.length;i++){
				if (servicos[i].equals(rmiUrl.substring(4))){
					Naming.unbind("rmi:"+servicos[i]);
				}
			}
			
			
			Naming.rebind(rmiUrl, obj); 
		}catch(Exception e){
			e.printStackTrace();
			log.error("[" + this.getClass().getName() + ".addObject()] não foi possivel adicionar o objeto ao registro RMI ");
		}
substitua a segunda thread por isso, adaptando ao seu problema acho que resolve... boa sorte >
N
maior_abandonado:
se o que você quer é iniciar o servidor via código, no cliente, você consegue da seguinte forma:
//inicializa o registry rmi
LocateRegistry.createRegistry(1099);
//coloca o objeto no registro
Naming.rebind(url, objeto);

Perceba que eu coloquei em 2 tags code, execute estes 2 em duas threads diferentes, pois a primeira linha ai trava a thread, fazendo com que nada depois dessa linha execute na mesma (se fossem colocadas na mesma thread não seria adicionado o objeto nela).

no passado, eu com um projeto que usa RMI tive problema fazendo isso na hora de colocar o objeto no registro, tava mantendo o registro aberto quando eu fechava o software, e depois ao re-abrir tinha uns sockets abertos de antes de fechar da primeira vez... ai eu tinha uns BindException, que penso que você provavelmente também teria, sendo assim eu resolvi tirando o objeto do registro e colocando-o novamente.
try{
			MinhaInterfaceRMI obj = this;
			String rmiUrl = "rmi://localhost:1099/aplicacao";
			
			String[] servicos = Naming.list(rmiUrl);
			
			for (int i=0; i<servicos.length;i++){
				if (servicos[i].equals(rmiUrl.substring(4))){
					Naming.unbind("rmi:"+servicos[i]);
				}
			}
			
			
			Naming.rebind(rmiUrl, obj); 
		}catch(Exception e){
			e.printStackTrace();
			log.error("[" + this.getClass().getName() + ".addObject()] não foi possivel adicionar o objeto ao registro RMI ");
		}
substitua a segunda thread por isso, adaptando ao seu problema acho que resolve... boa sorte >

Por isso faço parte do fórum do GUJ.

Bom, hoje mesmo farei isso e verei os resultados, qualquer coisa volto a postar aqui novamente.
Muito obrigado!

Att,

Nel

R

Bom Dia, eu também estou tentando rodar minha aplicação e também está dando erro do tipo:
Erro:java.rmi.ConnectException: Connection refused to host: localhost; nested exception is:
java.rmi.ConnectException: Connection refused to host: localhost; nested exception is:
java.net.ConnectException: Connection refused: connect
java.net.ConnectException: Connection refused: connect

O meu CLIENTE roda normalmente, mas quando vai acessar o SERVIDOR, dá esse erro.

Já tentei fazer várias coisas e mesmo assim ainda não consegui, se alguem puder me ajudar, ficarei muito Feliz.
Abaixo segue meu código,
Bjos,
Rebecca

SERVIDOR

/* 
    * To change this template, choose Tools | Templates 
    * and open the template in the editor. 
    */  
    package rmi;  
    import java.rmi.Naming;  
        import java.rmi.RemoteException;  
           
    /** 
    *  
    * @author Rebecca 
    */  
    public class Servidor  
        {  
                /** 
                 *  
                 * @throws RemoteException 
                 */  
                public Servidor() throws RemoteException  
            {  
                String localServico = "rmi://localhost:1099/InterfaceCalculoRemoto";  
                InterfaceCalculoRemoto objServidorRemoto = new ImplementacaoCalculoRemoto();  
           
                try  
                {  
                     Naming.rebind(localServico, objServidorRemoto);  
                }  
                catch (Exception e)  
                {  
                     e.printStackTrace();  
                }  
             }  
           
                /** 
                 *  
                 * @param args 
                 * @throws RemoteException 
                 */  
                public static void main(String[] args) throws RemoteException  
                {  
                      Servidor objServidor = new Servidor();  
                }  
        }

CLIENTE

/* 
    * To change this template, choose Tools | Templates 
    * and open the template in the editor. 
    */  
    package rmi;  
      
    import java.net.MalformedURLException;  
        import java.rmi.Naming;  
        import java.rmi.NotBoundException;  
        import java.rmi.RemoteException;  
        import javax.swing.JOptionPane;  
      
           
    /** 
    *  
    * @author Rebecca 
    */  
    public class Cliente {  
           
        /** 
         *  
         * @param args 
         */  
        public static void main(String[] args)  
            {  
                try {  
                       int val1 = Integer.parseInt(JOptionPane.showInputDialog("Entre com o primeiro valor"));  
                       String opcao[] = {"+", "-", "*", "/"};  
           
                       int operacao = JOptionPane.showOptionDialog(null, "Escolha uma das operacoes", "Tipo de operacao",  
                       0, JOptionPane.INFORMATION_MESSAGE, null, opcao, opcao[0]);  
           
                       int val2 = Integer.parseInt(JOptionPane.showInputDialog("Entre com o segundo valor"));  
           
                       InterfaceCalculoRemoto objCalculoRemoto = (InterfaceCalculoRemoto)Naming.lookup("rmi://localhost:1099/InterfaceCalculoRemoto");  
           
                       System.out.println("Servidor fala: O resultado é = " + objCalculoRemoto.metodo_calcular(val1, val2, operacao));  
                       objCalculoRemoto.mensagemServidor("Recebi a Resposta");  
                 }  
           
                    catch (MalformedURLException e)  
                    {  
                            System.out.println("Erro:" + e.toString());  
                            e.printStackTrace();  
                    }  
                    catch (RemoteException e)  
                    {  
                            System.out.println("Erro:" + e.toString());  
                            e.printStackTrace();  
                        }  
                    catch (NotBoundException e)  
                    {  
                            System.out.println("Erro:" + e.toString());  
                            e.printStackTrace();  
                        }  
                    catch (Exception e)  
                    {  
                            JOptionPane.showMessageDialog(null, "Entrada inválida", e.getMessage(), JOptionPane.ERROR_MESSAGE);  
                            System.exit(-1);  
                    }  
            }  
    }

IMPLEMENTAÇÃO CALCULOREMOTO

/* 
    * To change this template, choose Tools | Templates 
    * and open the template in the editor. 
    */  
    package rmi;  
      
    import java.rmi.RemoteException;  
        import java.rmi.server.UnicastRemoteObject;  
           
    /** 
    *  
    * @author Rebecca 
    */  
    public class ImplementacaoCalculoRemoto extends UnicastRemoteObject implements InterfaceCalculoRemoto  
        {  
          
        /** 
         *  
         * @throws RemoteException 
         */  
        public ImplementacaoCalculoRemoto() throws RemoteException  
            { }  
           
                /** 
                 *  
                 * @param mensagem 
                 * @throws RemoteException 
                 */  
        @Override  
                public void mensagemServidor(String mensagem) throws RemoteException  
        {  
              System.out.println("Cliente fala: " + mensagem);  
        }  
           
                /** 
                 *  
                 * @param val1 
                 * @param val2 
                 * @param op 
                 * @return 
                 * @throws RemoteException 
                 */  
        @Override  
                public double metodo_calcular(int val1, int val2, int op) throws RemoteException  
        {  
           double v1 = Double.valueOf(String.valueOf(val1));  
           double v2 = Double.valueOf(String.valueOf(val2));  
           
              if (op == 0)  
              {  
                  return (v1 + v2);  
              }  
              else  
                  if (op == 1)  
                  {  
                      return (v1 - v2);  
                  }  
                  else  
                      if (op == 2)  
                      {  
                          return (v1 * v2);  
                      }  
                      else  
                           if (op == 3)  
                           {  
                               return (v1 / v2);  
                            }  
             return 0;  
          }  
    }

INTERFACE CALCULOREMOTO

/* 
    * To change this template, choose Tools | Templates 
    * and open the template in the editor. 
    */  
    package rmi;  
      
    import java.rmi.Remote;  
        import java.rmi.RemoteException;  
           
    /** 
    *  
    * @author Rebecca 
    */  
    public interface InterfaceCalculoRemoto extends Remote  
        {  
                /** 
                 *  
                 * @param val1 
                 * @param val2 
                 * @param operacao 
                 * @return 
                 * @throws RemoteException 
                 */  
                public double metodo_calcular(int val1, int val2, int operacao) throws RemoteException;  
                /** 
                 *  
                 * @param mensagem 
                 * @throws RemoteException 
                 */  
                public void mensagemServidor(String mensagem) throws RemoteException;  
        }

Fico no aguardo, Obrigada

O

Pergunta básica: você está rodando o “cliente” e o “servidor” na mesma máquina?

R

Olá Oyama, estou sim.

:stuck_out_tongue:

O

Bem, espero que esteja dando start do “servidor” antes do “cliente”. :slight_smile:

Pode ser o firewall da sua maquina barrando o acesso.
Tente usar alguma ferramenta tipo telnet para tentar conectar nesta porta e ver se tem acesso, pois a mensagem tipicamente é de acesso negado.

R

Vixi, Desculpa a ignorancia, mas não entendo nada disso…rsrs
Sou novata nisso, acho que até da pra perceber pelo exemplo do trabalho que fiz…rsrs. O que eu fiz, foi o seguinte, fiz esses programinhas em netbeans, selecionei o arquivo e coloquei pra executar (não sei se só tem isso pra ser feito ou se tem mais alguma coisa), primeiro selecionei o cliente e executei, ele roda perfeitamente, quando o cliente envia a mensagem para o servidor que aparece esse erro. Já desabilitei meu firewall e mesmo assim dá erro. Eu li que teria de ir no cmd e fazer algumas coisas, mas nem sei como faço isso. De fato, nao sei o que fazer, se puder passar passo a passo pra mim, ficarei extremamente grata. Imagine que só criei os arquivos no netbeans e coloquei pra executar, como se eu estivesse feito um aplicativo desktop normal, onde crio as classes e depois de tudo pronto, só coloco pra executar e é aberto normalmente. Com o Rmi, sei que nao é somente isso, preciso de mais coisas, mas onde vou? como faço pra startar o servidor? o que preciso fazer para rodar essa simples aplicação? Me ajude, please…rsrsrs

O

Bem, agora achamos a causa do erro.

A coisa é bem simples: você tem duas classes - uma que implementa um Cliente e a outra que implementa um Servidor. Para que o Cliente funcione, você precisa startar o Servidor antes.
Acho que dá para rodar os dois no Netbeans. Eu não sei como, pois não uso o Netbeans. Se for rodar “na mão”, é só compilar o código e executar usando “java rmi.Servidor”.

R

Então eu já tentei fazer isso, mas mesmo assim continua dando o erro que mencionei.

Eu abri o cmd e digitei “java rmi.Servidor” e tbem deu erro do tipo “Não foi possível localizar nem carregar a classe principal rmi.Servidor”. De fato não sei mais o que eu faço…rsrs.

Só pra complementar, eu abri o cmd e fui nos diretórios da pasta do netbeansprojects tentei fazer o registro do rmi, apareceu que “esse comando não é reconhecido como comando interno ou externo, um programa operável ou um arquivo em lotes”.

Acredito que o erro não estão nas minhas classes, acho que está na forma de fazer rodar o rmi. De verdade, não sei o que fazer…rsrsr
O netbeans já compilou o arquivo, ja abri o cmd, fui nos diretórios, mas na hora de tentar fazer o rmiregistry, aparece o erro acima.

Como faço pra rodar isso??? Me ajudemmmmm…rsrsrs

M

Boa Tarde, será necessario primeiramente rodar a classe servidor, e depois rodar a classe cliente,

no netbeans e so entrar na classe servidora e clicar Shift+F6 fazendo o mesmo na classe cliente,

Obrigado

R

Boa Tarde Marcelo, Obrigada por ter respondido.
Mas então, eu já fiz isso tbem…rsrs… e naada. Já olhei as minhas classes, aparentemente está tudo correto, o Cliente roda certo, somente o Servidor que nao Roda, quando coloco pra executar a minha classe Servidor, aparece o erro do tipo:

Exception in thread “main” java.rmi.server.ExportException: Port already in use: 1099; nested exception is:
java.net.BindException: Address already in use: JVM_Bind
at sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:310)

Já desabilitei o firewall, ja limpei o código, coloquei pra debugar, fiz um monte de coisa já, massssssssssss não roda…rsrsrs

Já não sei o que faço mais.

:frowning:

M

Bom dia, geralmente essa Exception se da
quando a porta está sendo usada…tente mudá-la…coloca 1234…vou dar uma lida no seu codigo…mas faz o teste de mudar a porta…

M

Rebecca boa tarde arrumei seu servidor, ve se ele roda agora......

import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

/**
 *
 * @author Rebecca
 */
public class Servidor {

    /**
     *
     * @throws RemoteException
     */
    public Servidor() throws RemoteException {
       

        try {
           LocateRegistry.createRegistry(1234);
           Naming.rebind("rmi://localhost:1234/calc", new ImplementacaoCalculoRemoto());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws RemoteException {
       new Servidor();
    }
}
M

na Parte Cliente tive que fazer pequenas alterações, pois apesar de rodar o servidor e o cliente estava dando erro em tempo de execução

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import javax.swing.JOptionPane;

/**
 *
 * @author Rebecca
 */
public class Cliente {

    /**
     *
     * @param args
     */
    public static void main(String[] args) {
        try {
            InterfaceCalculoRemoto objCalculoRemoto = (InterfaceCalculoRemoto) Naming.lookup("rmi://localhost:1234/calc");

            int val1 = Integer.parseInt(JOptionPane.showInputDialog("Entre com o primeiro valor"));
            
            String opcao[] = {"+", "-", "*", "/"};

            int operacao = JOptionPane.showOptionDialog(null, "Escolha uma das operacoes", "Tipo de operacao",
                    0, JOptionPane.INFORMATION_MESSAGE, null, opcao, opcao[0]);

            int val2 = Integer.parseInt(JOptionPane.showInputDialog("Entre com o segundo valor"));
            
            double resultado = objCalculoRemoto.metodoCalcular(val1, val2, operacao);
            System.out.println("resposta é : " + resultado);
            objCalculoRemoto.mensagemServidor("Recebi a Resposta");
            
        } catch (MalformedURLException | RemoteException | NotBoundException e) {
            System.out.println("Erro:" + e.toString());
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, "Entrada inválida", e.getMessage(), JOptionPane.ERROR_MESSAGE);
            System.exit(-1);
        }
    }
}
M

alterei a classe ImplementacaoCalculoRemoto

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import javax.swing.JOptionPane;

/**
 *
 * @author Rebecca
 */
public class ImplementacaoCalculoRemoto extends UnicastRemoteObject implements InterfaceCalculoRemoto {

    /**
     *
     * @throws RemoteException
     */
    public ImplementacaoCalculoRemoto() throws RemoteException {
    }

    public void mensagemServidor(String mensagem) throws RemoteException {
        System.out.println("Cliente fala: " + mensagem);
    }

    @Override
    public double metodoCalcular(double val1, double val2, int operacao) throws RemoteException {
       
        if (operacao == 0) {
            return val1 + val2;
        } else if (operacao == 1) {
            return val1 - val2;
        } else if (operacao == 2) {
            return val1 * val2;
        } else if (operacao == 3) {
            try{
                if(val2 == 0){
                    throw new ArithmeticException("NÃO PODE DIVIDIR POR 0");
                }else{
            return val1 / val2;
            }
            }catch(Exception arithmeticException){
                JOptionPane.showMessageDialog(null, arithmeticException.toString());
            }
        }
        return 0;
    }
}
M

a interface

import java.rmi.Remote;
import java.rmi.RemoteException;

/**
 *
 * @author Rebecca
 */
public interface InterfaceCalculoRemoto extends Remote {

    /**
     *
     * @param val1
     * @param val2
     * @param operacao
     * @return
     * @throws RemoteException
     */
    public double metodoCalcular(double val1, double val2, int operacao) throws RemoteException;

    /**
     *
     * @param mensagem
     * @throws RemoteException
     */
    public void mensagemServidor(String mensagem) throws RemoteException;
}
R

Aiiiinnn que tudoooo Marcelooooo, nussss rodou perfeitamenteeee…rsrsrsr

Muito Obrigada mesmo, de coração Marcelo, vc me ajudou e muito, quebrou um galho enorme…rsrsrs

Um grande beijoo e mais uma vez, Obrigada.

Ficou perfeito…rsrsrs

M

não foi nada…espero ter ajudado…

qualquer coisa é só mandar o problema…se souber ajudarei…

Bjos

R

Com certeza farei isso, vou precisar e muito ainda…rsrs

Bjosss

Criado 7 de junho de 2010
Ultima resposta 9 de out. de 2012
Respostas 19
Participantes 5