“de java.rmi.ConnectException: Connection refused to host” lors de l'exportation d'un objet côté client

Je suis coincé avec ce pour au moins 5 heures maintenant et n'ont pas d'autres recours que de demander ici. Je suis en train d'écrire un RMI application. J'aimerais que le serveur de lier un objet distant (NoteBoardImpl ici), qui sera examiné par le client. Le Client passe son port d'écoute (NoteBoardListener ici) pour le serveur, l'auditeur est également un objet distant exportés par le client.

Je vous ai préparé un simple SSCCE ici, donc j'espère vraiment que quelqu'un puisse y jeter un œil. Toutes les classes sont dans le même dossier du package par défaut. Je sais que c'est déconseillé et j'ai partagé de la demande dans les trois pots, mais je voulais le garder aussi simple que possible ici.

Interface de commande à distance:

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

public interface INoteBoard extends Remote {
    public void test(INoteBoardListener listener) throws RemoteException;
}

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

public interface INoteBoardListener extends Remote {
    public void onNewText(String text) throws RemoteException;
}

Interfaces des implémentations:

import java.rmi.RemoteException;

public class NoteBoardImpl implements INoteBoard {
    @Override
    public void test(INoteBoardListener listener) throws RemoteException {
        listener.onNewText("server call the listener");
    }
}

import java.rmi.RemoteException;

public class NoteBoardListener implements INoteBoardListener {
    @Override
    public void onNewText(String text) throws RemoteException {
        System.out.println(text);
    }
}

Le Client et le serveur:

import java.rmi.Naming;
import java.rmi.server.UnicastRemoteObject;

public class Client {
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("2 arguments required:\nRMI_IP RMI_port");
            return;
        }
        System.setProperty("java.rmi.server.hostname", args[0]);
        try {
            INoteBoard nb = (INoteBoard) Naming.lookup(String.format("rmi://%s:%s/note", args[0], args[1]));
            INoteBoardListener l = (INoteBoardListener) UnicastRemoteObject.exportObject(new NoteBoardListener(), 0);
            nb.test(l);
            l.onNewText("client invokes listener");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

import java.rmi.Naming;
import java.rmi.server.UnicastRemoteObject;

public class Server {
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("2 arguments required:\nRMI_IP RMI_port");
            return;
        }
        System.setProperty("java.rmi.server.hostname", args[0]);
        try {
            INoteBoard noteBoard = (INoteBoard) UnicastRemoteObject.exportObject(new NoteBoardImpl(), 0);
            Naming.rebind(String.format("rmi://%s:%s/note", args[0], args[1]), noteBoard);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

J'ai essayé de simuler un système distribué à des fins de test et a couru le client sur une machine virtuelle. L'hôte VM network a les caractéristiques suivantes - IP de l'hôte = 192.168.56.1, VM IP = 192.168.56.101.

D'abord, j'ai couru le client et le serveur en local, en utilisant les commandes suivantes (en ayant commencé rmiregistry 1099 à l'avance). Le répertoire de travail est la racine du projet et les classes compilées sont en bin répertoire:

java -cp bin -Djava.rmi.server.codebase=http://student.agh.edu.pl/~grajewsk/bin/Server 192.168.56.1 1099

java -cp bin Client 192.168.56.1 1099

Et cela a fonctionné.

Puis j'ai exécuté le programme client sur la machine virtuelle à l'aide de la même commande et voici l'exception que j'ai eu:

java.rmi.ConnectException: Connection refused to host: 192.168.56.1; nested exception is: 
java.net.ConnectException: Connection refused
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:128)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:194)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:148)
at sun.proxy.$Proxy0.test(Unknown Source)
at Client.main(Client.java:14)
Caused by: java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:327)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:193)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:180)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:384)
at java.net.Socket.connect(Socket.java:546)
at java.net.Socket.connect(Socket.java:495)
at java.net.Socket.<init>(Socket.java:392)
at java.net.Socket.<init>(Socket.java:206)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:146)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
... 7 more

Remarquez comment l'objet est regardé avec succès dans le registre du serveur, puis le côté client de l'objet distant est exporté (avec succès) et l'exécution des pauses dans la 14-ème ligne, où j'essaie d'appeler une méthode sur l'objet côté serveur en passant l'objet côté client.

Je n'ai pas de pare-feu sur un de ces systèmes, les pings dans les deux directions vont parfaitement. Je sais qu'il doit y avoir un problème conceptuel ici et que j'ai sans doute mal compris quelque chose à propos du RMI. Je serais très reconnaissant de votre aide.

Le binaire de la base de code est sur mon étudiant serveur, ainsi que le code source. Je vous remercie à l'avance!

Pouvez-vous vous de ping 192.168.56.1 de 192.168.56.101?
Oui, comme je l'ai écrit "pings dans les deux directions vont parfaitement". De plus, je peux telnet pour le rmiregistry et les ports du serveur en dépit de la machine, je lance le serveur, donc je peux faire tourner le serveur sur l'hôte ou sur VM et peut se connecter par telnet pour les ports de l'autre machine.

OriginalL'auteur Wojtek | 2013-03-26