# RMI: Remote Object ohne Naming Service benutzen?



## RSchwarzkopf (28. Apr 2006)

Hallo,

mich lässt eine Behauptung von William Grosso in seinem Buch über RMI nicht mehr los. Seite 141, der Absatz mit Pfoten

Practically speaking (...) you use a "well-known-port" to connect to the server. That is, instead of using UnicastRemoteObject's zero-argument constructor, you pass in a port number. This can be convenient because it enables a client to bypass a naming service. (...)

Also irgendwie ist mir absolut noch nicht klar, wie das funktionieren soll. Okay, ich kenne dann den Endpunkt, und kann mir damit einen sun.rmi.transport.tcp.TCPEndpoint basteln. Soweit klar. Um das Objekt aber benutzen zu können benötige ich ja eine java.rmi.server.RemoteRef, genauergesagt eine sun.rmi.server.UnicastRef. Damit ich die erzeugen kann benötige ich wiederum eine sun.rmi.transport.LiveRef. Dabei nützt mir der Endpunkt jetzt ein bisschen was. Zusammen mit einer Object ID kann ich daraus die LiveRef basteln, daraus die UnicastRef und damit krieg ich dann sogar einen Stub (sofern ich die Klasse des Stubs habe, mit Proxies hab ich's noch nicht probiert) und kann das Objekt aufrufen. Mal davon abgesehen, das das erzeugen der Objekt ID ein ganz schöner Aufriss war (mangels passendem Konstruktor, die Jungs von Sun wissen sicher warum es den nicht gibt..), muss man die ja auch erstmal kennen..

Nun aber zu meiner eigentlichen Frage: Seh ich die ganze Sache zu technisch? Meint der vielleicht was ganz anderes damit?? Sowas vermute ich nämlich.. Hat vielleicht irgendeiner eine Idee was dem Mann da vorschweben könnte? Vielleicht hat jemand auch schonmal sowas implementiert??

Bin für jeden Tip dankbar!

MfG
Roland


----------



## Killerzwelch (18. Okt 2009)

Hi Roland,

ja, es geht, dass ist die Information die man überall im Netz findet.

Die Antwort auf die Frage wie ist:
Das Remote Object muss serialisiert werden und per UDP an den Client gesand werden
(das ist die Aufgabe, die sonst die RMIRegistry übernimmt). Im Code ist noch ein Broadcast enthalten der per UDP im lokalen Netz Rechner aufstöbert, dieser Teil kann ignoriert werden und ist nur der Vollständigkeit halber enthalten...

Die magische Methode, ist die *toStub()*-Methode (line 5) im zweiten Code-Ausschnitt, dies ist der Proxy für den Client, der serilisiert übers Netz geschickt werden muss.
Beispiel Code könnte so aussehen und sollte adptierbar sein: 

```
public class CalcRunner {

	public static void main(String[] args) throws Exception {
		// Send helo
		DatagramSocket socket = new DatagramSocket();
		DatagramPacket helo = new DatagramPacket("helo".getBytes(), 4, InetAddress.getByName("127.0.0.1"), 56789);
		socket.send(helo);
		
		// Receive reply (blocking call)
		byte[] replyBuf = new byte[1024];
		DatagramPacket reply = new DatagramPacket(replyBuf, replyBuf.length);
		socket.receive(reply);
		
		ByteArrayInputStream is = new ByteArrayInputStream( reply.getData() );
		ObjectInputStream in = null;
		Remote stub;

		in = new ObjectInputStream(is);
			
		stub = (Remote) in.readObject();
			
		in.close();

	    CalcClient cc = new CalcClient( (Calc) stub);
	    System.out.println( cc.add( 1, 2) );
}}
```


```
public class CalcProvider {
	public static void main(String[] args) throws Exception {
		CalcImpl ci = new CalcImpl();
		
	    Remote stub = RemoteObject.toStub( ci );

	    ByteArrayOutputStream bs = new ByteArrayOutputStream();
	    ObjectOutputStream out = null;
	    out = new ObjectOutputStream(bs);
	    out.writeObject(stub);
	    out.close();
	    
	    byte[] seri = bs.toByteArray();
	    
	    DatagramSocket serverSocket = new DatagramSocket( 56789 );
		
    	byte[] receiveData = new byte[4];
    	while(true) {
    		
    		DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
    		serverSocket.receive(receivePacket);
    		
    		InetAddress clientIp = receivePacket.getAddress();
    		int port = receivePacket.getPort();
    		
    		System.out.println( "Sending stub to whoever" );
    		
    		DatagramPacket sendPacket = new DatagramPacket(seri, seri.length, clientIp, port);
    		serverSocket.send(sendPacket);
	    
}}}
```

Hoffentlich erspart dies einigen Menschen grauenvolle Transformationsversuche und API Recherchen 

Schönen Gruß
Roland
(ich denke wir haben uns an der Uni Siegen bereits kennengelernt?!)


----------



## tuxedo (19. Okt 2009)

Wow, das sowas geht wusste ich nicht...

Vielleicht steh ich auch auf dem Schlauch, aber in welchem Szenario würde man sowas einsetzen?

- Alex


----------

