Java RMI:客户端似乎可以找到服务器,但总是会得到“连接被拒绝”

时间:2018-07-21 21:20:55

标签: java rmi

原始问题:

我遇到了一个问题,该问题不允许我的客户端-服务器程序在本地范围之外运行。 该程序必须处理服务器(称为“代理”)和客户端的网络,它们可以在其中创建或遵循某些“主题”。为了做到这一点,客户必须连接到托管其主题列表和其子网订阅的代理(经纪人也必须能够担当客户角色,但我仍然必须从事此工作)。

我正在与一个扮演代理角色的朋友在Eclipse中进行测试,但是每次我尝试与他联系时,我都会遇到相同的错误,那就是您看到的错误。 我已经尝试了各种方式,在我告诉你的情况下,我已经输入了朋友的dns地址,该程序似乎找到了它,因为在错误中它指示了他的pc的本地地址,所以我不了解我们为什么会收到此错误。

错误

当我尝试连接到正在收听的朋友时,会发生以下情况:

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

最后更新

这是该代码的最新版本,问题尚未解决。

服务器端:

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();
    }
}

客户端:

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();
    }
}

1 个答案:

答案 0 :(得分:0)

System.setProperty("java.rmi.server.hostname","localhost");

这是问题所在。您需要进行设置,但是要设置为服务器主机的公共IP地址,可以从外部访问该地址。

"localhost"是您要设置为 last 的对象。

编辑:

super();

如果您有防火墙,这将永远无法工作。更改为使用固定端口。最简单的解决方案是使用LocateRegistry.createRegistry(Registry.REGISTRY_PORT)在进程内部创建RMI注册表,然后使用super(REGISTRY_PORT)将您的远程对象导出到相同的端口,这实际上应默认发生。并确保防火墙转发端口1099。