RMI über Netzwerk (nicht lokal !)

hi,

windows
Code:
java -classpath .;[pfad zu deinem projekt] -jar jTestTool.jar -v

linux
Code:
java -classpath .:[pfad zu deinem projekt] -jar jTestTool.jar -v

ich schau mir deinen code mal an...
 
hmm, also bei mir funktioniert alles anstandts los....

aber als kleinen tip, klassen namen werden bei java groß geschrieben und das default package sollte man nicht verwenden...

schau nochmal richtig das die firewall aus ist, die policies passen und die rechner erreichbar sind...

hmf
 
Hi,
Verdammt !! Sowas hab ich mir gedacht,die linux Rechner haben irgendwie ein Problem... aber echt seltsam, weil Netzwerkdrucken über cups geht , nfs Freigaben gehn nur nix rmi, na ja auf jeden fall mal vielen Dank für die Mühe... ist dann wohl ein Netzwerk Problem...
 
So,
lag dann echt irgendwie am Netzwerk...

Habe jetzt RMI mit Custom RMIServerSocketFactory am laufen, im Netzwerk!!
Ist ganz ok, weil man die Ports bestimmen und auf die Sockets einfluss nehmen kann...
Ist auch nicht so viel mehr Aufwand, aber kennt jemand spezielle Nachteile zufällig
Na ja bin erstmal froh das es läuft...
Danke nochmal.
Ich stehe auch gern für Fragen bereit...

Grüße Zerrome
 
Hallo zerrome,

habe derzeit das gleiche Problem. Bei mir läuft der RMI-Server Dient auf einem Rechner mit Firewall. Port 1099 ist in der Firewall freigeschaltet und auf dem Server lokal kann sich der Client verbinden und läuft auch einwandfrei. Nur wenn ich den Client von einem anderen Rechner aus aufrufe, läuft bis einschließlich zum "Naming.lookup" alles recht langsam und beim Aufruf einer RemoteInterface-Methode erhalte ich dann eine "connection timeout"-Exception.
Jetzt würde ich gerne die Sache mit der Custom RMIServerSocketFactory ausprobieren. Wie erstelle ich diese? Kannst Du mir eventuell Beispielcode geben!?

Vielen Dank im Vorraus und schöne Grüße,

Sebastian
 
Hallo,
ich glaube, dass probelm liegt daran, dass die daten bei rmi über zufällige ports übertragen werden, will man also den port bestimmen, muss man wohl auf custom sockets zurückgreifen andere möglichkeit hab ich nicht gefunden (korrigiert mich wenn ich falsch liege...),

sieht bei mir so aus:



1. klasse die serversocketfactory implementiert
Code:
import java.io.IOException;
import java.net.ServerSocket;
import java.rmi.server.RMIServerSocketFactory;

public class ServerSocketFactory implements RMIServerSocketFactory {
   
    private final int port;

    //konstruktor , übergabe port 
    public ServerSocketFactory(int port) throws IOException{
    	this.port=port;
    }
    
    //erstellt socket auf port
    public ServerSocket createServerSocket(int ports)throws IOException{
    	ServerSocket ss=new ServerSocket(port);
        return ss;
    }
}

2. klasse die client socketfactory implementiert
Code:
import java.io.IOException;
import java.io.Serializable;
import java.net.Socket;
import java.rmi.server.RMIClientSocketFactory;

public class ClientSocketFactory implements RMIClientSocketFactory, Serializable {

 	private static final long serialVersionUID = 2091251397464010038L;
	private final int port;
    private final String host;
    
    
    //konstruktor
    public ClientSocketFactory(String host,int port) {    
    	this.port=port; 
    	this.host=host;
    }
    
    //nötige create Socket Methode
    public Socket createSocket(String hostc, int portc)throws IOException{ 
    	Socket socket=new Socket(host,port);
    	return socket;    	
    }
    
}

3. klasse die server interface implementiert (ich gehe mal davon aus, dass du deine eigene hast...)

4. klasse die den server implementiert

Code:
 public static void main(String[] args)throws IOException{ 	  		
	  final int rPort=2000;	              //registry port
	  final int comPort=2001;  	  //daten port
	  
	  try {
		  
		  if (System.getSecurityManager() == null) {
			    System.setSecurityManager(new SecurityManager());
			}		  
		  Server myServer = new Server();		  
		  RMIClientSocketFactory csf = new ClientSocketFactory("192.168.0.11",comPort); 
		  RMIServerSocketFactory ssf = new ServerSocketFactory(comPort);
		  
		  serverInterface stub=(serverInterface) UnicastRemoteObject.exportObject(myServer, 0, csf, ssf);
		  System.out.println("ComPorts: "+comPort);
		  
		  LocateRegistry.createRegistry(rPort);	
		  System.out.println("Registry Port: "+rPort);
		  
		  Registry registry = LocateRegistry.getRegistry( rPort);	  		
		  registry.rebind("Server",stub );
		  
		  System.out.println("Remote Object: "+registry.list()[0]);
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		 
	
  }

jetzt noch der client:

1. die gleiche klasse wie oben bei punkt 2 (clientsocketfactory)
2. das server interface also von punkt 3
3. den client
Code:
public static void main(String[] args)throws Exception {
		final int port=2000;
		final String ip="192.168.0.11";
				
		try {
			
			RMISecurityManager sm=new RMISecurityManager();
			System.setSecurityManager(sm);						
			
			Registry registry=LocateRegistry.getRegistry(ip,port);
			System.out.println("Registry Remote obj: "+registry.list()[0]);
			
		    serverInterface server = (serverInterface)registry.lookup(registry.list()[0]);   		    
		    		    
		    }
		
		    catch (Exception ex)
		    {
		    	System.out.println(ex);
		     }

	}

so läuft das bei mir wenn ich die beiden ports bei der firewall, für die registry und die daten freigebe.

der link hier hat mir zu der lösung verholfen (ist sogar kleine verschlüsselung implementiert)

http://java.sun.com/j2se/1.4.2/docs/guide/rmi/socketfactory/index.html#11

gruß zerrome
 
Hallo,

IMHO kann man das auch ohne eigene RMISocketFactory hinbekommen.
http://blogs.sun.com/jmxetc/entry/connecting_through_firewall_using_jmx

Du kannst die RMI Remote Objects zum selben Port exportieren wie die RMI Registry:

In vielen System exportiert man nur ein einziges Remote Object welches dann die Methodenaufrufe der Clients entgegennimmt und dann intern entsprechend weiter dispatched. So macht das beispielsweise Springs RMI Remoting.

Unser IService Interface:
Java:
/**
 * 
 */
package de.tutorials.services;

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

/**
 * @author Thomas.Darimont
 *
 */
public interface IService extends Remote  {
    String businessOperation(String arg) throws RemoteException;
}

Unsere UpperCaseService Implementierung:
Java:
/**
 * 
 */
package de.tutorials.services.internal;

import de.tutorials.services.IService;

/**
 * @author Thomas.Darimont
 * 
 */
public class UpperCaseService implements IService {

	@Override
	public String businessOperation(String arg) {
		return arg.toUpperCase();
	}

}

Unsere PrependHelloService Implementierung:
Java:
/**
 * 
 */
package de.tutorials.services.internal;

import de.tutorials.services.IService;

/**
 * @author Thomas.Darimont
 * 
 */
public class PrependHelloService implements IService {

	@Override
	public String businessOperation(String arg) {
		return "Hello: " + arg;
	}

}

Java:
/**
 * 
 */
package de.tutorials.rmi;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import de.tutorials.services.IService;
import de.tutorials.services.internal.PrependHelloService;
import de.tutorials.services.internal.UpperCaseService;

/**
 * @author Thomas.Darimont
 * 
 */
public class Server {
	public static void main(String[] args) throws Exception {
		int port = 3000;
		Registry registry = LocateRegistry.createRegistry(port);
		System.out.println(registry);
		registry.rebind(IService.class.getName(), UnicastRemoteObject
				.exportObject(new UpperCaseService(), port));
		registry.rebind(IService.class.getName() + "_Hello",
				UnicastRemoteObject.exportObject(new PrependHelloService(),
						port));
		Thread.sleep(Integer.MAX_VALUE);
	}
}

Unser Client:
Java:
/**
 * 
 */
package de.tutorials.rmi;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import de.tutorials.services.IService;

/**
 * @author Thomas.Darimont
 * 
 */
public class Client {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		Registry registry = LocateRegistry.getRegistry(3000);
		IService service = (IService) registry.lookup(IService.class.getName());
		IService service1 = (IService) registry.lookup(IService.class.getName()
				+ "_Hello");
		System.out.println(service.businessOperation("Hallo"));
		System.out.println(service1.businessOperation("Tom"));
	}

}

Client starten mit JVM Property:
-Djava.rmi.server.ignoreStubClasses=true

Ausgabe:
Code:
Server:
RegistryImpl[UnicastServerRef [liveRef: [endpoint:[192.168.1.33:3000](local),objID:[0:0:0, 0]]]]

Client:
HALLO
Hello: Tom

Wenn nun an der Firewall wie in diesem Beispiel der Port 3000 freigeschaltet wird sollte es damit funktionieren.

Gruß Tom
 

Anhänge

  • de.tutorials.training-rmi.zip
    6,8 KB · Aufrufe: 25
Zurück