简体   繁体   中英

Java RMI: client seems to find server but always gets “connection refused”

ORIGINAL QUESTION:

I've got a problem that doesn't allow my client-server program to work outside the local scope. The program must handle a network of servers (called "broker") and clients where they can create or follow some "topics". In order to do this a client must connect to a broker which hosts his list of topics and subscriptions of his subnet (broker also have to be capable to play client role, but i still have to work on this).

I'm testing it in Eclipse with a friend who plays the role of broker but everytime i try to connect to him i get the same error, that is the one you can see. I've tried in various ways, in the case i show you i've put the dns address of my friend, and the program seems to find it because in the error it indicates the local address of his pc, so i don't understand why we get this error.

ERROR

This is what happens when i try to connect to my friend who is listening:

java.rmi.ConnectException: Connection refused to host: 192.168.1.57; nested exception is: 
    java.net.ConnectException: Connection timed out: connect
    at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619)
    at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
    at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:130)
    at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:227)
    at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:179)
    at com.sun.proxy.$Proxy0.connectClient(Unknown Source)
    at forumPCAD.PCADClient.connectTo(PCADClient.java:47)
    at forumPCAD.PCADClient.MenuConsole(PCADClient.java:133)
    at forumPCAD.PCADClient.main(PCADClient.java:217)
Caused by: java.net.ConnectException: Connection timed out: connect
    at java.net.DualStackPlainSocketImpl.connect0(Native Method)
    at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at java.net.Socket.connect(Socket.java:538)
    at java.net.Socket.<init>(Socket.java:434)
    at java.net.Socket.<init>(Socket.java:211)
    at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
    at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:148)
    at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
    ... 9 more

LAST UPDATE

This is the latest version of the code, and issues are not solved yet.

Server Side:

package forumPCAD;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NoSuchObjectException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

import addressHandlers.RmiAddressHandler;
import addressHandlers.ipChecker;

public class PCADBroker extends UnicastRemoteObject implements Broker, Client {

    private static final long serialVersionUID = 1L;
    protected Client brokerStub;                                        //Lo stub da esportare corrispondente a questo broker
    protected Broker superBroker;                                       //Il riferimento al broker a cui questo si connette
    List<Topic> superBrokerTopics;                                      //I topic del superbroker a cui questo è iscritto
    List<Topic> brokerTopics;                                           //I topic gestiti da questo broker
    List<Client> stubsClients;                                          //Gli stub dei client connessi a questo broker
    ConcurrentHashMap<Topic, List<String>> brokerSubscriptions;         //Le associazioni tra i topic e i nomi dei client iscritti ad essi
    protected String brokerName;                                        //Il nome del broker
    protected String brokerPublicIP;                                    //L'indirizzo IP del broker
    protected String brokerURL;                                         //L'url completo del broker

    public PCADBroker(String brokerName) throws RemoteException {
        super();
        brokerStub = null;
        superBroker = null;
        superBrokerTopics  = new CopyOnWriteArrayList<Topic>();
        brokerTopics = new CopyOnWriteArrayList<Topic>();
        stubsClients = new CopyOnWriteArrayList<Client>();
        brokerSubscriptions = new ConcurrentHashMap<Topic, List<String>>();
        this.brokerName = brokerName;
        this.brokerPublicIP = ipChecker.checkPublicIp();
        this.brokerURL = "rmi://" + brokerPublicIP + "/" + brokerName;
    }

    @Override
    public void startListening() throws RemoteException, MalformedURLException {
        System.setProperty("java.security.policy","file:./sec.policy");
        if(System.getSecurityManager() == null) System.setSecurityManager(new SecurityManager());
        try {
            LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
        } catch(RemoteException e){
            LocateRegistry.getRegistry(Registry.REGISTRY_PORT);
        }
        System.out.println("Istanza PCADBroker creata");
        Naming.rebind(brokerName, this);
        System.out.println("Il Broker \"" + brokerName + "\" è in ascolto all'URL: " + brokerURL);
    }

    public void stopListening() throws RemoteException, MalformedURLException, NotBoundException {
        if(System.getSecurityManager() == null) System.setSecurityManager(new SecurityManager());
        try {
            LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
        } catch(RemoteException e){
            LocateRegistry.getRegistry(Registry.REGISTRY_PORT);
        }
        Naming.unbind(brokerName);
        System.out.println("Broker ha smesso di ascoltare all'URL: " + brokerURL);
    }

    @Override
    public synchronized boolean connectClient(Client stubClient) throws RemoteException{
        if(stubsClients.isEmpty())
            return stubsClients.add(stubClient);
        for(Client client : stubsClients) {
            if(client.getName().equals(stubClient.getName()))
                return false;
        }
        return stubsClients.add(stubClient);
    }
    //Utilizza il foreach perchè in questo caso il metodo è di sola lettura e confronto.

    @Override
    public synchronized boolean disconnectClient(Client stubClient) throws RemoteException{
        if(stubsClients.isEmpty())
            return false;
        for(Client client : stubsClients) {
            if(client.getName().equals(stubClient.getName())) {
                stubsClients.remove(stubsClients.indexOf(client));
                return true;
            }
        }
        return false;
    }
    //Verificare che sia il metodo migliore per rimuovere da una lista CopyOnWrite.

    @Override
    public List<Topic> getBrokerTopics() throws RemoteException{
        List<Topic> brokerTopicsList = new CopyOnWriteArrayList<Topic>(brokerTopics);
        if(!superBrokerTopics.isEmpty()) {
            List<Topic> superBrokerTopicsList = new CopyOnWriteArrayList<Topic>(superBrokerTopics);
            brokerTopicsList.addAll(superBrokerTopicsList);
        }
        return brokerTopicsList;
    }
    //La lista ritornata dovrà contenere i topic del broker + i topic del superbroker a cui il broker è iscritto.

    @Override
    public synchronized boolean subscribeClient(Client subscriber, String topicTitle) throws RemoteException{
        String subscriberName = subscriber.getName();
        Topic theTopic = null;

        //Ricerca del topic tra quelli originari del broker

        if(!brokerTopics.isEmpty()) {
            for(Topic topic : brokerTopics)
                theTopic = (topic.getTitle().equals(topicTitle) ? topic : null);
        }
        if(theTopic != null) {
            if(!brokerSubscriptions.get(theTopic).contains(subscriberName))
                return brokerSubscriptions.get(theTopic).add(subscriberName);
            return false;
        }

        //Ricerca del topic tra quelli originari del superBroker

        if(!superBrokerTopics.isEmpty()) {
            for(Topic topic : superBrokerTopics)
                theTopic = (topic.getTitle().equals(topicTitle) ? topic : null);
        }
        if(theTopic != null) {
            if(!brokerSubscriptions.get(theTopic).contains(subscriberName))
                return brokerSubscriptions.get(theTopic).add(subscriberName);
            return false;
        }
        return false;
    }
    //Il client può vedere nella lista i topic del superbroker a cui il broker è iscritto e iscrivervisi a sua volta.
    //L'iscrizione è sempre memorizzata in brokerSubscriptions.

    @Override
    public synchronized boolean unsubscribeClient(Client subscriber, String topicTitle) throws RemoteException{
        String subscriberName = subscriber.getName();
        Topic theTopic = null;

        //Ricerca del topic tra quelli originari del broker

        for(Topic topic : brokerTopics) {
            theTopic = topic.getTitle().equals(topicTitle) ? topic : null;
        }
        if(theTopic != null) {
            if(brokerSubscriptions.get(theTopic).contains(subscriberName))
                return brokerSubscriptions.get(theTopic).remove(subscriberName);
            return false;
        }

        //Ricerca del topic tra quelli originari del superBroker

        if(!superBrokerTopics.isEmpty()) {
            for(Topic topic : superBrokerTopics)
                theTopic = topic.getTitle().equals(topicTitle) ? topic : null;
        }
        if(theTopic != null) {
            if(brokerSubscriptions.get(theTopic).contains(subscriberName))
                return brokerSubscriptions.get(theTopic).remove(subscriberName);
            return false;
        }
        return false;
    }
    //Il client può vedere nella lista i topic del superbroker a cui si era iscritto e disiscrivervisi.
    //L'iscrizione viene tolta da brokerSubscriptions.

    @Override
    public synchronized boolean publishTopic(Topic topic) throws RemoteException{
        for(Topic aTopic : brokerTopics) {
            if(topic.getTitle().equals(aTopic.getTitle()))
                return false;
        }
        if(brokerTopics.add(topic)){
            brokerSubscriptions.put(topic, new CopyOnWriteArrayList<String>());
            return true;
        }
        return false;
    }
    //Controlla che non ci sia già un topic con titolo uguale, poi aggiunge il nuovo topic nella lista del broker.

    @Override
    public synchronized boolean publishAndBroadcastNotification(String publisherName, String topicTitle, String notification) throws RemoteException{
        Topic theTopic = null;
        for(Topic aTopic : brokerTopics)
            theTopic = aTopic.getTitle().equals(topicTitle) ? aTopic : null;
        if(theTopic == null)
            for(Topic aTopic : superBrokerTopics)
                theTopic = aTopic.getTitle().equals(topicTitle) ? aTopic : null;
        if(theTopic == null){
            Topic newTopic = new PCADTopic(publisherName, topicTitle, topicTitle + " (Topic generato automaticamente)");
            return publishTopic(newTopic);
        }
        if(theTopic.getPublisherUsername().equals(publisherName)) {
            if(brokerSubscriptions.get(theTopic).isEmpty())
                return true;
            brokerSubscriptions.get(theTopic).forEach(subscriber->{
                try {
                    for(Client client : stubsClients){
                        if(client.getName().equals(subscriber))
                            client.receiveNotification(publisherName, topicTitle, notification);
                    }
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            });
            return true;
        }
        return false;
    }
    //Decidere se comunicare la creazione automatica del topic, magari usando il topic di servizio dell'idea.

    @Override
    public boolean connectTo(String IpAddress, String brokerName) throws MalformedURLException, RemoteException {
        //return connectTo("rmi://" + IpAddress + "/" + brokerName);
        try {
            System.setProperty("java.security.policy","file:./sec.policy");
            if (System.getSecurityManager() == null) 
                System.setSecurityManager(new SecurityManager());
            LocateRegistry.getRegistry(IpAddress, Registry.REGISTRY_PORT);
            superBroker = (Broker)  Naming.lookup(brokerName);
            try {
                brokerStub = (Client) UnicastRemoteObject.exportObject(this,0);
            }
            catch(RemoteException e) {
                brokerStub = (Client) UnicastRemoteObject.toStub(this);
            }
            return superBroker.connectClient(brokerStub);
        }
        catch (RemoteException | NotBoundException e) {
            e.printStackTrace();
            return false;
        }
    }

    //Questo broker si connette al superBroker indicato e inizializza la lista in cui memorizzare i topic a cui si iscriverà.

    @Override
    public boolean disconnectFromBroker() throws RemoteException, NoSuchObjectException {
        return superBroker == null ? false : superBroker.disconnectClient(brokerStub);
    }

    public List<Topic> getTopics() throws RemoteException{
        return superBroker == null ? null : superBroker.getBrokerTopics();
    }

    @Override
    public boolean subscribeTo(String topicTitle) throws RemoteException {
        if(superBroker == null)
            return false;
        if(superBroker.subscribeClient(brokerStub, topicTitle)) {
            for(Topic topic : superBroker.getBrokerTopics()) {
                if(topic.getTitle().equals(topicTitle)) {
                    if(superBrokerTopics.add(topic)) {
                        brokerSubscriptions.put(topic, new CopyOnWriteArrayList<String>());
                        return true;
                    }
                }
            }
        }
        return false;
    }
    //Questo broker si iscrive al topic del superBroker, poi recupera il topic stesso dalla lista del superBroker e lo aggiunge a superBrokerTopics.
    //Non controlla se ci sono topic con lo stesso titolo.

    @Override
    public boolean unsubscribeFrom(String topicTitle) throws RemoteException {
        if(superBroker == null)
            return false;
        if(superBroker.unsubscribeClient(brokerStub, topicTitle)) {
            for(Topic topic : superBroker.getBrokerTopics()) {
                if(topic.getTitle().equals(topicTitle)) {
                    //publishAndBroadcastNotification(publisherName, topicTitle, "This topic has been removed");
                    if(superBrokerTopics.remove(topic)) {
                        brokerSubscriptions.remove(topic);
                        return true;
                    }
                }
            }
        }
        return false;
    }
    //Questo broker si disiscrive dal topic del superBroker, poi recupera il topic stesso dalla lista del superBroker e lo rimuove da superBrokerTopics.
    //Idea: aggiunger un topic di servizio dove il broker può inviare comunicazioni come questa

    @Override
    public boolean receiveNotification(String publisher, String topicTitle, String notification) throws RemoteException {
        return publishAndBroadcastNotification(publisher, topicTitle, notification);
    }
    //Gira la notifica, mettendosi come autore della stessa, 

    @Override
    public boolean publishTopicOnBroker(Topic topic) throws RemoteException {
        System.out.println("Un broker non può pubblicare topic su altri broker");   //renderli inutilizzabili in qualche modo
        return false;
    }
    //Idea: aggiunger un topic di servizio dove il broker può inviare comunicazioni.

    @Override
    public String getName() throws RemoteException{
        return brokerName;
    }

    @Override
    public boolean verifySubscription(Topic topic) throws RemoteException{
        return superBroker.verifySubscription(this, topic);
    }

    @Override
    public boolean verifySubscription(Client subscriber, Topic topic) throws RemoteException{
        return brokerSubscriptions.isEmpty() ? false : brokerSubscriptions.get(topic) == null || brokerSubscriptions.get(topic).isEmpty() ? false : brokerSubscriptions.get(topic).contains(subscriber.getName());
    }

    @Override
    public boolean sendNotification(String topicTitle, String notification) throws RemoteException {
        System.out.println("Un broker non può inviare notifiche");          //renderli inutilizzabili in qualche modo
        return false;
    }
    //Idea: aggiunger un topic di servizio dove il broker può inviare comunicazioni.

    private void MenuConsole() throws RemoteException, MalformedURLException, NotBoundException { //Aggiungere opzione visualizza iscrizioni
        try{
            Scanner keyboard = new Scanner(System.in);
            boolean exit = false;
            boolean listening = false;
            boolean connectedToBroker = false;
            RmiAddressHandler rmiAddressHandler = new RmiAddressHandler();
            System.out.println(getName());
            while(!exit) {
                System.out.println("Cosa si desidera fare?");
                System.out.println("1) " + (listening ? "Smettere di ascoltare" : "Mettersi in ascolto"));
                if(listening) System.out.println("2) Vedere la lista dei Client collegati");
                System.out.println("3) Leggere la lista dei Topic di questo Broker");
                System.out.println("4) " + (connectedToBroker ? "Disconnettersi dal superBroker" : "Connettersi ad un altro Broker"));
                if(connectedToBroker) {
                    System.out.println("5) Leggere la lista dei Topic del superBroker");
                    System.out.println("6) Iscriversi ad un topic (rendendolo visibile ai propri Client)");
                    System.out.println("7) Disiscriversi da un topic (eliminando le iscrizioni dei propri Client)");
                }
                System.out.println("0) Uscire " + (listening || connectedToBroker ? "(Chiudendo le connessioni attive)" : ""));
                switch(Integer.parseInt(keyboard.nextLine())) {
                case 1: 
                    if(listening) stopListening();
                    else startListening();
                    listening = !listening;
                    break;
                case 2:
                    if(!listening) {
                        System.out.println("Scelta non valida, riprovare");
                        break;
                    }
                    if(stubsClients.isEmpty())
                        break;
                    for(Client client : stubsClients)
                        System.out.println("Username: " + client.getName());
                    break;
                case 3:
                    if(brokerTopics.isEmpty()) {
                        System.out.println("Nessun Topic presente");
                        break;
                    }
                    for(Topic topic : brokerTopics)
                        System.out.println("Titolo: " + topic.getTitle());
                    break;
                case 4:
                    if(connectedToBroker) {
                        disconnectFromBroker();
                        connectedToBroker = false;
                    }
                    else {
                        System.out.println("Inserire l'indirizzo del broker: ");
                        String url = keyboard.nextLine();
                        String address = rmiAddressHandler.getAddressFromRmiAddress(url);
                        String brokerName = rmiAddressHandler.getNameFromRmiAddress(url);
                        connectedToBroker = connectTo(address, brokerName);
                    }
                    break;
                case 5:
                    if(!connectedToBroker) {
                        System.out.println("Scelta non valida, riprovare");
                        break;
                    }
                    List<Topic> topicList = getTopics();
                    if(topicList.isEmpty()) {
                        System.out.println("Nessun Topic presente");
                        break;
                    }
                    for(Topic topic : topicList) {
                        System.out.println("Titolo: " + topic.getTitle() + (verifySubscription(topic) ? "\tIscritto" : ""));
                    }
                    break;
                case 6:
                    if(!connectedToBroker) {
                        System.out.println("Scelta non valida, riprovare");
                        break;
                    }
                    System.out.println("Inserire il titolo del Topic: ");
                    subscribeTo(keyboard.nextLine());
                    break;
                case 7:
                    if(!connectedToBroker) {
                        System.out.println("Scelta non valida, riprovare");
                        break;
                    }
                    System.out.println("Inserire il titolo del Topic: ");
                    unsubscribeFrom(keyboard.nextLine());
                    break;
                case 0:
                    exit = true;
                    if(listening) stopListening();
                    break;
                default:
                    System.out.println("Scelta non valida, riprovare");
                }
            }
            keyboard.close();
            System.exit(0);
        }
        catch(Exception e) {
            stopListening();
            disconnectFromBroker();
        }
    }

    public static void main(String[] args) throws RemoteException, MalformedURLException, NotBoundException {
        Scanner keyboard = new Scanner(System.in);
        System.out.println("Inserire il nome del Broker da istanziare:");
        PCADBroker broker = new PCADBroker(keyboard.nextLine());
        broker.MenuConsole();
        keyboard.close();
    }
}

Client Side:

package forumPCAD;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NoSuchObjectException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.CopyOnWriteArrayList;

import addressHandlers.RmiAddressHandler;


public class PCADClient implements Client {

    private static final long serialVersionUID = 1L;

    private String username;
    private Client stub;
    private Broker broker;
    List<String> notifications;

    public PCADClient(String username) throws RemoteException {
        this.username = username;
        stub = null;
        broker = null;
        notifications = new CopyOnWriteArrayList<String>();
    }

    public boolean connectTo(String IpAddress, String brokerName) throws MalformedURLException, RemoteException {
        try {
            System.setProperty("java.security.policy","file:./sec.policy");
            if (System.getSecurityManager() == null) 
                System.setSecurityManager(new SecurityManager());
            LocateRegistry.getRegistry(IpAddress, Registry.REGISTRY_PORT);
            broker = (Broker)  Naming.lookup("rmi://" +IpAddress + "/" + brokerName);
            try {
                stub = (Client) UnicastRemoteObject.exportObject(this,0);
            }
            catch(RemoteException e) {
                stub = (Client) UnicastRemoteObject.toStub(this);
            }
            return broker.connectClient(stub);
        }
        catch (RemoteException | NotBoundException e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean disconnectFromBroker() throws RemoteException, NoSuchObjectException {
        if(!broker.disconnectClient(stub))
            return false;
        LocateRegistry.getRegistry(Registry.REGISTRY_PORT);
        return UnicastRemoteObject.unexportObject(this,false);
    }

    public List<Topic> getTopics() throws RemoteException{
        return broker.getBrokerTopics();
    }

    @Override
    public boolean subscribeTo(String topicTitle) throws RemoteException {
        return broker.subscribeClient(stub, topicTitle);
    }

    @Override
    public boolean unsubscribeFrom(String topicTitle) throws RemoteException {
        return broker.unsubscribeClient(stub, topicTitle);
    }

    @Override
    public boolean publishTopicOnBroker(Topic topic) throws RemoteException {
        return broker.publishTopic(topic);
    }

    @Override
    public boolean receiveNotification(String publisher, String topicTitle, String notification) throws RemoteException{
        return notifications.add("---\nNotifica da: " + publisher + "\nSul topic: "+ topicTitle + "\nTesto: " + notification + "\n---");
    }

    @Override
    public boolean sendNotification(String topicTitle, String notification) throws RemoteException {
        return broker.publishAndBroadcastNotification(username, topicTitle, notification);
    }

    public String getName() {
        return username;
    }

    public void setName(String username) {
        this.username = username;
    }

    public boolean verifySubscription(Topic topic) throws RemoteException {
        return broker.verifySubscription(this, topic);
    }

    private void MenuConsole() throws RemoteException, MalformedURLException, NotBoundException {   
        try {
        Scanner keyboard = new Scanner(System.in);
        boolean exit = false;
        boolean connectedToBroker = false;
        RmiAddressHandler rmiAddressHandler = new RmiAddressHandler();
        while(!exit) {
            System.out.println("Cosa si desidera fare?");
            System.out.println("1) " + (connectedToBroker ? "Disconnettersi dal Broker" : "Connettersi ad un Broker"));
            if(connectedToBroker) {
                System.out.println("2) Leggere la lista dei topic");
                System.out.println("3) Pubblicare un nuovo topic");
                System.out.println("4) Iscriversi ad un topic");
                System.out.println("5) Disiscriversi da un topic");
                System.out.println("6) Inviare una notifica su un topic (creandolo se non esiste)");
            }
            System.out.println("7) Controllare le notifiche");
            System.out.println("0) Esci " + (connectedToBroker ? "(Chiudendo le connessioni attive)" : ""));
            switch(Integer.parseInt(keyboard.nextLine())) {
            case 1:
                if(connectedToBroker) {
                    disconnectFromBroker();
                    connectedToBroker = false;
                }
                else {
                    System.out.println("Inserire l'indirizzo del broker: ");
                    String url = keyboard.nextLine();
                    String address = rmiAddressHandler.getAddressFromRmiAddress(url);
                    String brokerName = rmiAddressHandler.getNameFromRmiAddress(url);
                    connectedToBroker = connectTo(address, brokerName);
                }
                break;
            case 2:
                if(!connectedToBroker) {
                    System.out.println("Scelta non valida, riprovare");
                    break;
                }
                List<Topic> topicList = getTopics();
                if(topicList.isEmpty()) {
                    System.out.println("Nessun Topic presente");
                    break;
                }
                for(Topic topic : topicList) {
                    System.out.println("Titolo: " + topic.getTitle() + (verifySubscription(topic) ? "\tIscritto" : ""));
                }
                break;
            case 3:
                if(!connectedToBroker) {
                    System.out.println("Scelta non valida, riprovare");
                    break;
                }
                System.out.println("Inserire un titolo per il nuovo Topic: ");
                String title = keyboard.nextLine();
                System.out.println("Inserire una descrizione per il nuovo Topic: ");
                String description = keyboard.nextLine();
                publishTopicOnBroker(new PCADTopic(username, title, description));
                break;
            case 4:
                if(!connectedToBroker) {
                    System.out.println("Scelta non valida, riprovare");
                    break;
                }
                System.out.println("Inserire il titolo del Topic: ");
                subscribeTo(keyboard.nextLine());
                break;
            case 5:
                if(!connectedToBroker) {
                    System.out.println("Scelta non valida, riprovare");
                    break;
                }
                System.out.println("Inserire il titolo del Topic: ");
                unsubscribeFrom(keyboard.nextLine());
                break;
            case 6:
                if(!connectedToBroker) {
                    System.out.println("Scelta non valida, riprovare");
                    break;
                }
                System.out.println("Inserire il titolo del Topic: ");
                String topicTitle = keyboard.nextLine();
                System.out.println("Scrivere il testo della notifica: ");
                String notification = keyboard.nextLine();
                sendNotification(topicTitle, notification);
                break;
            case 7:
                if(notifications.isEmpty()) {
                    System.out.println("Non ci sono notifiche");
                    break;
                }
                for(String aNotification : notifications)
                    System.out.println(aNotification);
                break;
            case 0:
                if(connectedToBroker)
                    disconnectFromBroker();
                exit = true;
                break;
            default:
                System.out.println("Scelta non valida, riprovare");
            }
        }
        keyboard.close();
        System.exit(0);
        }
        catch (Exception e){
            disconnectFromBroker();
        }
    }

    public static void main(String[] args) throws RemoteException, MalformedURLException, NotBoundException {
        Scanner keyboard = new Scanner(System.in);
        System.out.println("Inserire il nome del Client da istanziare:");
        PCADClient client = new PCADClient(keyboard.nextLine());
        client.MenuConsole();
        keyboard.close();
    }
}
System.setProperty("java.rmi.server.hostname","localhost");

This is the problem. You need to set it, but to the public IP address of the server host, the one that can be accessed from outside.

"localhost" is the last thing you would ever want to set it to.

EDIT:

super();

This will never work if you have firewalls. Change it to use a fixed port. Simplest solution is to create the RMI Registry inside the process with LocateRegistry.createRegistry(Registry.REGISTRY_PORT) and then export your remote object on the same port, with super(REGISTRY_PORT) , which should indeed happen by default. And ensure that your firewall forwards port 1099.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM