Visualizzazione dei risultati da 1 a 6 su 6

Discussione: Connessione RMI

  1. #1
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    47

    Connessione RMI

    Salve,
    sto cercando di capire il funzionamento della connessione RMI tra client e server.
    Praticamente ho questo fatto questo server per la gestione remota di uno stack

    RMIServer.java
    codice:
    package rmiserver;
    import java.rmi.registry.LocateRegistry;
    import java.rmi.registry.Registry;
    
    public class RMIServer {
    
        public static void main(String[] argv) throws Exception {
    
            StackImp s = new StackImp(10);
            Registry reg = LocateRegistry.createRegistry(1099);
            reg.rebind("xyz", s);
            System.out.println("RMI Server pronto....");
            System.out.println("In attesa della richiesta...");
    
        }
    }
    Stack.java
    codice:
    package rmiserver;
    import java.rmi.*;
    
    public interface Stack extends Remote {
    
        public void push(int p) throws RemoteException;
    
        public int pop() throws RemoteException;
    }

    StackImp.java
    codice:
    package rmiserver;
    
    import java.rmi.*;
    import java.rmi.server.*;
    
    public class StackImp extends UnicastRemoteObject implements Stack {
    
        private int tos, data[], size;
    
        public StackImp() throws RemoteException {
            super();
        }
    
        public StackImp(int s) throws RemoteException {
            super();
            size = s;
            data = new int[size];
            tos = -1;
        }
    
        public void push(int p) throws RemoteException {
    
            tos++;
            data[tos] = p;
        }
    
        public int pop() throws RemoteException {
            int temp = data[tos];
            tos--;
            return temp;
        }
    
    }
    I seguenti, invece, sono i file che compongono il client

    RMIClient.java
    codice:
    package rmiclient;
    import java.rmi.*;
    
    public class RMIClient {
    
        public static void main(String[] argv) throws Exception {
            
            String url = "rmi://localhost/";
            Stack s = (Stack) Naming.lookup(url+"xyz");
            s.push(25);
    //        System.out.println("Push: " + s.push(25));
            System.out.println("Pop: " + s.pop());
    
        }
    }
    Stack.java
    codice:
    package rmiclient;
    import java.rmi.*;
    
    public interface Stack extends Remote {
    
        public void push(int p) throws RemoteException;
    
        public int pop() throws RemoteException;
    }
    Quando lancio il server in esecuzione riesco a vedere entrambi i messaggi
    codice:
    System.out.println("RMI Server 
    System.out.println("In attesa della richiesta...");
    Quando lancio il client, invece, mi viene sollevata questa eccezione
    codice:
    Exception in thread "main" java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
        java.lang.ClassNotFoundException: rmiserver.Stack (no security manager: RMI class loader disabled)
        at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
        at java.rmi.Naming.lookup(Naming.java:101)
        at rmiclient.RMIClient.main(RMIClient.java:19)
    Caused by: java.lang.ClassNotFoundException: rmiserver.Stack (no security manager: RMI class loader disabled)
        at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:556)
        at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:646)
        at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:311)
        at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:255)
        at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1559)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1515)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
        ... 3 more
    Java Result: 1
    Dove sto sbagliando?
    Grazie

  2. #2
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Nel client tu stai cercando di ottenere un oggetto di tipo rmiclient.Stack, ma il server sta spedendo un oggetto di tipo rmiserver.Stack. Quando si ha a che fare con la serializzazione (e RMI usa, appunto, la serializzazione) i nomi delle classi sono importanti... e quando parlo di "nome della classe" intendo dire il Fully Qualified Name, ovvero il nome completo di package.

    Quindi hai, al momento, due possibilità:

    1) O fai combaciare i nomi dei package lato server e lato client (ad esempio, spostando la classe Stack in un package che possa essere usato anche dal client)

    2) O rendi disponibile al client nel CLASSPATH la classe usata dal server


    Io opterei per la prima, più facile... costruirei sia lato server che lato client un package (ad esempio "transfer") e lì dentro metterei l'interfaccia Stack, così da non avere conflitti con i nomi.

    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  3. #3
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    47
    Scusa, credo mi stia sfuggendo un passaggio. Ho spostato il file RMIClient.java nel package rmiserver dove può avvedere alla classe Stack.java. Può andare bene questo passaggio? Il server viene lanciato come sempre; il client, invece, ora da questo errore:

    codice:
    Exception in thread "main" java.rmi.server.ExportException: Port already in use: 1099; nested exception is: 
        java.net.BindException: Indirizzo già in uso
        at sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:330)
        at sun.rmi.transport.tcp.TCPTransport.exportObject(TCPTransport.java:238)
        at sun.rmi.transport.tcp.TCPEndpoint.exportObject(TCPEndpoint.java:411)
        at sun.rmi.transport.LiveRef.exportObject(LiveRef.java:147)
        at sun.rmi.server.UnicastServerRef.exportObject(UnicastServerRef.java:208)
        at sun.rmi.registry.RegistryImpl.setup(RegistryImpl.java:152)
        at sun.rmi.registry.RegistryImpl.<init>(RegistryImpl.java:137)
        at java.rmi.registry.LocateRegistry.createRegistry(LocateRegistry.java:203)
        at rmiserver.RMIServer.main(RMIServer.java:20)
    Caused by: java.net.BindException: Indirizzo già in uso
        at java.net.PlainSocketImpl.socketBind(Native Method)
        at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:382)
        at java.net.ServerSocket.bind(ServerSocket.java:375)
        at java.net.ServerSocket.<init>(ServerSocket.java:237)
        at java.net.ServerSocket.<init>(ServerSocket.java:128)
        at sun.rmi.transport.proxy.RMIDirectSocketFactory.createServerSocket(RMIDirectSocketFactory.java:45)
        at sun.rmi.transport.proxy.RMIMasterSocketFactory.createServerSocket(RMIMasterSocketFactory.java:345)
        at sun.rmi.transport.tcp.TCPEndpoint.newServerSocket(TCPEndpoint.java:666)
        at sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:319)
        ... 8 more
    Ultima modifica di capcla; 30-07-2014 a 16:49

  4. #4
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    47
    Ho risolto. Il problema del messaggio di errore del post precedente dipendeva dal fatto che credevo di stare a lanciare il file RMIClient invece l'ide mi lanciava il file RMIServer. Tornando al discorso del CLASSPATH come lo dovrei risolvere? Io uso sia windows, sia linux sia mac

  5. #5
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Quote Originariamente inviata da capcla Visualizza il messaggio
    Tornando al discorso del CLASSPATH come lo dovrei risolvere? Io uso sia windows, sia linux sia mac
    Non ho capito il problema... che c'entra il CLASSPATH col sistema operativo?
    Il CLASSPATH è un insieme di risorse (file JAR o directory) in cui la JVM va a reperire le classi. Generalmente, quando si ha a che fare con una applicazione che risiede in un JAR, il CLASSPATH è definito dentro al MANIFEST del JAR stesso... Ciò che devi assicurare alla JVM è di trovare le classi necessarie lungo il CLASSPATH.


    Quindi, il server dovrebbe avere un package (ad esempio "transfer") con dentro la classe Stack e lo stesso il client. Punto.
    Graficamente parlando:

    Nel server:


    codice:
    +rmiserver
    |   |
    |   +--> RMIServer.class
    |
    +transfer
        |
        +--> Stack.class

    Nel client:


    codice:
    +rmiclient
    |   |
    |   +--> RMIClient.class
    |
    +transfer
        |
        +--> Stack.class

    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  6. #6
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    47
    Scusa, stavo confondendo la path con il classpath. Ora credo di aver capito. Grazie di tutto

Tag per questa discussione

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.