# RMI & Connection refused to host



## boesi (16. Aug 2007)

moin

Ich habe eine kleine Client-/Serveranwendung geschrieben, die mittels RMI kommuniziert.

Im lokalen Netz funktioniert das auch wunderbar über Rechnergrenzen hinweg (konkret: Serverprogramm läuft in einer virtuellen Machine [VMware] und das Clientprogramm hab ich auf 2 Rechnern erfolgreich getestet.)

Nun soll das Serverprogramm aber auf einem "richtigen" Server (Windows Server 2003) laufen und die Clientprogramme auf beliebigen Rechnern im Internet. Also auf dem Server den Port 1099 freigegeben - aber funktioniert nicht.

Eine Verbindung kann ich scheinbar aufbauen, zumindest liefern folgende Zeilen keine Exception:

```
Registry reg = LocateRegistry.getRegistry(Konst.addrServer);
RMIConnector server = (RMIConnector) reg.lookup(Konst.rmiName);
```
Das Serverprogramm gibt dabei aus:

```
16.08.2007 14:32:14 sun.rmi.server.UnicastServerRef logCall
FEINER: RMI TCP Connection(3)-91.64.35.41: [91.64.35.41: sun.rmi.registry.Regist
ryImpl[0:0:0, 0]: java.rmi.Remote lookup(java.lang.String)]
```
Aber der direkt darauf folgende entfernte Methodenaufruf führt beim Server zu gar keiner Reaktion, und der Client liefert "java.rmi.ConnectException: Connection refused to host: ..."

Dabei ist es egal, ob der Client per NAT ins Internet geht oder direkt eine im I-Net gültige IP-Adresse bekommt. Die IP-Adresse des Servers ist direkt erreichbar. Firewall gib's auf beiden Seiten keine, auf dem Server läuft ein Packetfilter (in dem wie gesagt Port 1099 freigeschalten ist). Einen Securitymanager verwende ich nicht. Andere Dienste auf dem Server wie zB Tomcat sind ohne Probleme erreichbar.

Und was mach ich nun? <= bin ziemlich ratlos


Vielen Dank schon mal für eure Hilfe
cu boesi


Hier der komplette Stacktrace des Clientprogramms:

```
java.rmi.ConnectException: Connection refused to host: ***hostname***; nested exception is: 
	java.net.ConnectException: Connection timed out: connect
	at sun.rmi.transport.tcp.TCPEndpoint.newSocket(Unknown Source)
	at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source)
	at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source)
	at sun.rmi.server.UnicastRef.invoke(Unknown Source)
	at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unknown Source)
	at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source)
	at $Proxy0.login(Unknown Source)
	at bnclient.RMIClient.login(RMIClient.java:49)
	at bnclient.Login.login(Login.java:74)
	at bnclient.Login$EvtKeys.keyReleased(Login.java:52)
	at java.awt.Component.processKeyEvent(Unknown Source)
	at javax.swing.JComponent.processKeyEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
	at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(Unknown Source)
	at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(Unknown Source)
	at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source)
	at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.Dialog$1.run(Unknown Source)
	at java.awt.event.InvocationEvent.dispatch(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)
Caused by: java.net.ConnectException: Connection timed out: connect
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.PlainSocketImpl.doConnect(Unknown Source)
	at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
	at java.net.PlainSocketImpl.connect(Unknown Source)
	at java.net.SocksSocketImpl.connect(Unknown Source)
	at java.net.Socket.connect(Unknown Source)
	at java.net.Socket.connect(Unknown Source)
	at java.net.Socket.<init>(Unknown Source)
	at java.net.Socket.<init>(Unknown Source)
	at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(Unknown Source)
	at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(Unknown Source)
	... 39 more
```


----------



## L-ectron-X (17. Aug 2007)

Port geöffnet?


----------



## boesi (17. Aug 2007)

L-ectron-X hat gesagt.:
			
		

> Port geöffnet?


Welchen Port und auf welcher Seite meinst du?
Auf dem Server ist der Port 1099, wie schon gesagt, offen. Und das Serverprogramm scheint die Verbindung ja auch zu akzeptieren (soweit ich RMI bisher verstanden hab).


cu boesi


----------



## L-ectron-X (17. Aug 2007)

boesi hat gesagt.:
			
		

> Auf dem Server ist der Port 1099, wie schon gesagt, offen.


OK, dann bau doch erst mal einen RMISecurityManager ein.


----------



## boesi (22. Aug 2007)

'Tschuldigung dass ich erst jetzt antworte, ich war die letzten Tage ausser Landes (... naja fast, zumindest offline)



			
				L-ectron-X hat gesagt.:
			
		

> OK, dann bau doch erst mal einen RMISecurityManager ein.


Meinst du auf Client- oder Server-Seite?
Auf jeden Fall hatte ich den auf beiden Seiten am Anfang mit drin, weil steht ja so in jedem Tutorial beschrieben. Hab den dann aber rausgenommen, weil es nur Zugriffsverweigerungen gab. Ausserdem war ich der Meinung, dass der SecurityManager nichts mit dem Problem hier zu tun hat (aber wahrscheinlich wird wohl doch zwischen Verbindungen im LAN und WAN unterschieden). Und ich benutze RMI nur um entfernte Methoden aufzurufen und nicht um Code zu übertragen, der auf der anderen Seite ausgeführt werden soll.

=====================================================
[Eigentlich sollte hier ein etwas länglicher Teil hin, der meine Probleme mit dem Security Manager beschreibt. Stattdessen funktioniert der Security Manager nun im LAN - ich hasse Tutorials, die einem nur die Hälfte erzählen.]

Im Client hab ich nun eine Methode connect mit dem Inhalt:

```
if (System.getSecurityManager() == null) {
	System.setSecurityManager(new RMISecurityManager());
}
Registry reg = LocateRegistry.getRegistry(Konst.addrServer);
RMIConnector server = (RMIConnector) reg.lookup(Konst.rmiName);
return server;
```
Die main-Methode des Servers tut folgendes:

```
if (System.getSecurityManager() == null) {
      System.setSecurityManager(new RMISecurityManager());
}
try {  // ja  das ist Absicht, ich will kein zusätzliches Programm starten müssen
      LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
} catch (RemoteException exc) { [...]  }
try {
      // BNServer implementiert das Interface RMIConnecter, das wiederum das Interface Remote implementiert                        
      RMIConnector rmiConn = new BNServer();
      RMIConnector rmiStub = (RMIConnector) UnicastRemoteObject.exportObject(rmiConn, 0);
      RemoteServer.setLog(System.out);
      Registry reg = LocateRegistry.getRegistry();
      reg.rebind("BNServer", rmiStub);
} catch (Exception exc) { [...] }
```
Die Policy-Dateien haben jeweils den gleichen Inhalt:

```
grant {
	permission java.security.AllPermission;
};
```
Die Policy geb ich nun beim starten jeweils mit "-Djava.security.policy=Policy-Datei" an. Im LAN funktioniert das auch inklusive Zugriff auf MySQL. Im WAN funktioniert "reg.lookup" - aka liefert keine Exception. Aber die eigentliche Methode auf dem Server wird nicht aufgerufen - also auch nix mit Exception. Der Client kommt dann irgendwann mit:

```
java.rmi.ConnectException: Connection refused to host: berufsnavigator.de; nested exception is:
        java.net.ConnectException: Connection timed out: connect
```
Und das ganze ist davon unabhängig ob ich einen SecurityManager verwende oder nicht.


cu boesi


----------



## L-ectron-X (22. Aug 2007)

Und wie sieht dein URL für den Server aus?


----------



## boesi (23. Aug 2007)

L-ectron-X hat gesagt.:
			
		

> Und wie sieht dein URL für den Server aus?


im lokalen Fall einfach der DNS-Name - murphy2k
sprich der Client verwendet 'LocateRegistry.getRegistry("murphy2k")'
den Server starte ich mit 'java -cp %CP% -Djava.rmi.server.hostname=murphy2k -Djava.security.policy=%PolicyFile% bnserver.BNServer'

Beim Server im Internet verwende ich entsprechend einfach den Domainnamen. Die IP-Adresse funktioniert genausowenig.


cu boesi


----------



## L-ectron-X (23. Aug 2007)

Setze doch mal den Protokollnamen noch davor.
Also rmi:// oder http://


----------



## boesi (23. Aug 2007)

L-ectron-X hat gesagt.:
			
		

> Setze doch mal den Protokollnamen noch davor.
> Also rmi:// oder http://


Du meinst in etwa so: 'java -cp %CP% -Djava.rmi.server.hostname=rmi://murphy2k -Djava.security.policy=%PolicyFile% bnserver.BNServer' ? 
Das Serverprogramm läßt sich so starten. Wenn ich im Client 'LocateRegistry.getRegistry("rmi://murphy2k");' angeb, liefert das darauf folgende lookup die Exception:

```
java.rmi.UnknownHostException: Unknown host: rmi://murphy2k; nested exception is: 
	java.net.UnknownHostException: rmi://murphy2k
	...
```
Interessant wird's, wenn ich im Client das rmi:// weglass. Dann wird genau diese Exception erst durch den Aufruf der entfernten Methode ausgelöst.

Mit HTTP ist's das gleiche.

cu boesi


----------



## L-ectron-X (23. Aug 2007)

Naja, der Client soll zu einer entfernten RMIRegistry Verbindung aufnehmen und dort ein Remote-Objekt suchen/finden, welches mit einem Namen dort registriert ist.
Die Suche eines Remote-Objektes in der entfernten RMIRegistry sollte in etwa so aussehen:

```
RemoteObject obj = (RemoteObject)Naming.lookup("http://host/name");
```


----------



## Guest (26. Aug 2007)

boesi hat gesagt.:
			
		

> L-ectron-X hat gesagt.:
> 
> 
> 
> ...



schreib die offentliche IP-Adresse des Gateway-Routers anstelle von "murphy2k"


----------



## boesi (26. Aug 2007)

L-ectron-X hat gesagt.:
			
		

> Naja, der Client soll zu einer entfernten RMIRegistry Verbindung aufnehmen und dort ein Remote-Objekt suchen/finden, welches mit einem Namen dort registriert ist.
> Die Suche eines Remote-Objektes in der entfernten RMIRegistry sollte in etwa so aussehen:
> 
> ```
> ...




```
java.net.MalformedURLException: invalid URL scheme: [url]http://murphy2k/BNServer[/url]
```
wenn ich statt http rmi nehm, funktioniert alles [nicht] wie gehabt - besteht zwischen dieser und meiner zweigeteilten Variante (die ich nebenbei direkt von Sun hab) überhaupt ein praktischer Unterschied?


cu boesi


----------



## boesi (26. Aug 2007)

Anonymous hat gesagt.:
			
		

> schreib die offentliche IP-Adresse des Gateway-Routers anstelle von "murphy2k"


Ähm zu murphy2k funktioniert alles, was nicht funktioniert ist der Server im Internet (dessen Domain ich hier nicht bekanntgeb - ein klein wenig Privatsphäre muss sein).

Der Server ist direkt über eine öffentliche IP erreichbar. Der Client ist über einen Router und Kabelmodem ans Internet angebunden. Aber die Probleme bestehen auch, wenn ich den Rechner mit dem Client direkt ans Modem häng (und dann eine öffentliche IP bekommt).


cu boesi


----------

