“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!
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
Vous devez vous connecter pour publier un commentaire.
Voici ce que j'avais à faire pour aller au fond de cette.
savoir quel est le port qu'il utilise pour le RMI (c'est éphémère, donc il devrait changer pour chaque processus de création du serveur).
sur le client VM, utilisez nc ou telnet pour vérifier que vous pouvez vous connecter au port. Si cela échoue, vous avez probablement un pare-feu/iptables question.
utiliser wireshark pour vérifier votre client est en fait en essayant de se connecter au port/ip combo que vous avez appris à partir de l'étape #2.
Rappelez-vous, juste parce que vous pouvez exécuter la commande ping, ne signifie pas que vous pouvez vous connecter à un port donné. Cochez aussi "iptables-L".
Aussi, De nommage dit de ne pas mettre le régime de la composante de l'URL. Le format doit être //host:port/nom, de sorte que vous devriez vérifier.
Si vous utilisez une connexion NAT de votre VM, essayez une passerelle de connexion.. C'est peut-être juste que vous êtes de problème, sinon, si vous souhaitez utiliser NAT, vous devez configurer une redirection de port (qui n'est probablement pas facile avec le RMI). Même si cela n'explique pas pourquoi vous pouvez vous connecter à RMIRegistry de la part du client.
Je suis à l'aide d'un Hôte uniquement l'adaptateur dans VirtualBox. Je ne suis pas vraiment sûr de savoir comment il émule le réseau. Je vais essayer comblé carte plus tard.
OriginalL'auteur user931366
Ok, enfin résolu. Le problème, c'est que je passais le même
java.rmi.server.hostname
argument dans les deux programmes, ce qui signifie que le client et le serveur obtenu l'adresse du serveur ici. Il s'est avéré, que si le client veut exporter ses propres objets, il doit fournir sa propre adresse IP à l'java.rmi.server.hostname
. De cette façon, tout fonctionne bien.Donc, pour résumer, je devais donner 3 arguments pour le serveur:
RMI_IP RMI_port server_hostname
Et 3 analogue arguments pour le client:
RMI_IP RMI_port client_hostname
OriginalL'auteur Wojtek