RMI rmi / observer

duschata

Mitglied
Hallo Alle,
bei der Suche nach einem guten RMI-Designpattern bin ich auf folgenden Artikel in diesem Formum gestoßen:

http://www.java-forum.org/netzwerkprogrammierung/22948-observer-ueber-rmi.html

Die Beispiele von SEMI funktionieren nur, wenn Server und Client auf dem selber Rechner laufen. Sobald ich den Client auf einem anderen Rechner starte, bekomme ich eine

Java:
 ava.rmi.ConnectException: Connection refused to host: 127.0.1.1; nested exception is:

+ bei Beispiel 1:

Java:
Connection refused to host: 127.0.1.1; nested
exception is: 
        
        java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
        at $Proxy0.addCounterListener(Unknown Source)
        at swing.CounterClient.initCounter(CounterClient.java:45)

+ bei Beispiel 2:
Java:
 at $Proxy0.addObserver(Unknown Source)
        at console.Client.main(Client.java:24)

Wo ist mein Denkfehler? Beide Rechner enthalten den gleichen Code, stubs sind generiert und wie gesagt, auf einem Rechner läuft es. Namensauflösung geht auch, habe es sogar mit IPs probiert (und habe den Thread in diesem Forum darüber auch schon gelesen)...

Hat jemand eine Idee oder Code zu observer/rmi, der garantiert funktioniert?

Gruß Tom
 

chalkbag

Bekanntes Mitglied
127.0.0.1 ist nur eine lokal verwendbare Adresse, also der local loopback, falls man das so sagen kann. Wenn du den entfernen Rechner ansprechen willst, musst du die "richtige" IP verwenden, also eher sowas wie 192.168.178.1, oder eben den Rechnernamen.

Zusäztlich sind zugriffe auf den gleichen Rechner unnd Zugriffe von außen für die meisten Firewalls nicht das gleiche ;)
 

duschata

Mitglied
127.0.0.1 ist nur eine lokal verwendbare Adresse, also der local loopback, falls man das so sagen kann. Wenn du den entfernen Rechner ansprechen willst, musst du die "richtige" IP verwenden, also eher sowas wie 192.168.178.1, oder eben den Rechnernamen.

Zusäztlich sind zugriffe auf den gleichen Rechner unnd Zugriffe von außen für die meisten Firewalls nicht das gleiche ;)

Die Rechner haben beide keine Firewalls. Als Server-Host habe ich beim Client selbsverständlich die IP Adresse des Servers eingetragen. Beide Rechner sind im gleichen Subnetz. Der Zugriff auf die rmiregistry von Clientseite geht:

Client (192.168.1.111)
Java:
telnet 192.168.1.123 1099
Trying 192.168.1.123...
Connected to 192.168.1.123.
Escape character is '^]'.

Und auf Serverseite (192.168.1.123)

Java:
18.02.2011 13:59:57 sun.rmi.server.UnicastServerRef logCall
FEINER: RMI TCP Connection(1)-192.168.1.111: [192.168.1.111: sun.rmi.registry.RegistryImpl[0:0:0, 0]: java.rmi.Remote lookup(java.lang.String)]

Gruß Tom
 
Zuletzt bearbeitet:

duschata

Mitglied
Hallo chalkbag und alle, die den Beitrag gelesen haben,

das Problem ist jetzt gelöst. Tatsächlich klappt die Verbindung zwischen Server und Client, weil hier die nach aussen sichtbare Adresse übermittelt wird. Merkwürdigerweise wird ab diesem Zeitpunkt dann aber die locahost Adresse übermittelt und die weitere Kommunikation schlägt fehl.
Ein Kurzfix wäre beim Aufruf des Programms, die nach aussen sichtbare Adresse zu übermitteln:

Code:
 -Djava.rmi.server.hostname=192.168.xxx.xxx

Nun will man aber in den meisten Fällen ja nicht, dass der Benutzer beim Starten des Clients erst seine IP-Adresse in irgendein Batch oder Shellscript einträgt :)

Ein kleiner Workarround beim Starten des Clients schafft hier Abhilfe, Vorraussetzung ist allerdings, dass die interne Namensauflösung im Netz funktioniert. Es wird allerdings sicher auch Möglichkeiten geben über die System.properties die nach aussen sichtbare Adresse herauszufinden. Für Tipps bin ich hier auch dankbar:

Java:
Properties currentProperties = System.getProperties();
String hostname ="";
try
{
	hostname = java.net.InetAddress.getLocalHost().getHostName();
}
catch (UnknownHostException unknownHostException)
{
	unknownHostException.printStackTrace();
}

currentProperties.put("java.rmi.server.hostname", hostname);
System.out.println("Hostname: " + hostname);
System.setProperties(currentProperties);
 
T

tuxedo

Gast
Hatte solche Probleme mit RMI nie. Typischerweise tritt das auf, wenn mit der Namensauflösung irgendwas nicht stimmt. AFAIK nimmt RMI den Hostnamen, löst den dann zur IP auf und verankert diese dann in den RemoteObjekten. Meist klappt die Verbindung vom Client zum Server, aber umgekehrt, via Callback, klappt's dann nicht mehr.

Wenn hier an irgendeiner stelle "127.0.0.1" bei rauskommt, dann stimmt die Namensauflösung an irgend einer Stelle nicht.

Gruß
Alex
 
Zuletzt bearbeitet von einem Moderator:

duschata

Mitglied
Grundsätzlich stimmt das. Einige Linux-Distributionen fügen jedoch bei der Installation in die /etc/hosts einen Eintrag in folgender Art ein:

Code:
127.0.0.1 HOSTNAME

Entfernt man diesen Eintrag, dann geht auch alles wie gewohnt. Leider kann man einem Benutzer nicht zumuten in dieser Datei zu editieren. Möglicherweise hat der dazu auch nicht die Rechte.

Die Schwierigkeiten tauchen auch nur dann auf, wenn die Kommunikation bidirektional ist. Genau bei der update Methode im Observer-Pattern fliegt mir alles um die Ohren, wenn nicht die nach aussen sichtbare Netzwerkadresse vom Client übermittelt wird. Alle Namens- und Reverselookups funktionieren in dem getesteten Netz einwandfrei, daran kann es also nicht liegen.

Viele Grüße Tom
 
T

tuxedo

Gast
Grundsätzlich stimmt das. Einige Linux-Distributionen fügen jedoch bei der Installation in die /etc/hosts einen Eintrag in folgender Art ein:

Code:
127.0.0.1 HOSTNAME

Entfernt man diesen Eintrag, dann geht auch alles wie gewohnt. Leider kann man einem Benutzer nicht zumuten in dieser Datei zu editieren. Möglicherweise hat der dazu auch nicht die Rechte.

Ja, das ist mit bekannt. Und es ist mir immer noch ein Rätsel wozu dieser Eintrag gut sein soll.
Wenn jemand erklären kann warum es Sinn macht den eigenen Hostnamen zu 127.0.0.1 aufzulösen: Nur her damit ...

Die Schwierigkeiten tauchen auch nur dann auf, wenn die Kommunikation bidirektional ist. Genau bei der update Methode im Observer-Pattern fliegt mir alles um die Ohren, wenn nicht die nach aussen sichtbare Netzwerkadresse vom Client übermittelt wird. Alle Namens- und Reverselookups funktionieren in dem getesteten Netz einwandfrei, daran kann es also nicht liegen.

Der Client erstellt das Callback-Objekt. Sobald es die RMI Schicht passiert, wird RMI anhand des Hostnamens die IP in das Callback-Objekt eintragen und das Objekt dem Server zur verfügung stellen.
Ruft der nun eine Methode im Callback Objekt beim Client auf, stellt der Server eine neue Socketverbindung zum Client her. Hierfür benutzt er die IP die im Callback-Objekt drin steckt.

Wenn hier 127.0.0.1 drin steht, dann würde das heissen, dass der Client seinen eigenen Hostnamen nicht erwartet zu einer nicht-loopback-IP auflöst.

Ist der Client eine Windows-Maschine, ist hier beim testen der Namensauflösung u.U. vorsicht geboten. Windows ist so "schlau" und benutzt nicht nur reines DNS, sondern mitunter auch das NetBios zur Namensauflösung. Java hingegen wird, AFAIK, nur DNS benutzen.

Hast du mal probiert mit Java auf Clientseite den Clienthostnamen in eine IP aufzulösen? Was kommt dabei raus?

Gruß
Alex

P.S. Wiedermal 1:0 für SIMON. Hier gäbe es dieses Problem nicht ;-)
 

duschata

Mitglied
Hallo Alex,
danke für deinen Beitrag, das Wichtigste steht im Footer. Ich werde Simon nehmen. :)
Da ich das Programm, was ich in RMI-implementieren wollte eh 3-Schichtig aufgebaut hatte (POJO-Controller, Vermittlungsschicht, Client-UI) brauche ich für die Migration zu Simon nur ein paar Zeilen zu ändern. Alles funktioniert erstmal im Minimaltest (vor allen Dingen hinter NAT, das wäre mein nächstes RMI-Problem gewesen), hoffe das bleibt auch so....
Viele Grüße

Tom
 

Ähnliche Java Themen

Neue Themen


Oben