# Java - Socketprogrammierung



## RelaX (25. Nov 2013)

Guten Tag,

auf der Suche nach einer geeigneten Lösung versuche ich jetzt mein Vorhaben mit Sockets zu lösen.

Wie man einfache Strings über Socket schickt ist mir bereits bekannt und stellt auch keine so große Herausforderung dar.

Jetzt kommt meine Frage.

Wie schaffe ich es Objekte die mittels serialisierung über Objectstream übertragen werden, auseinander zuhalten?

Vorgestellt hätte ich es mir so ähnlich wie bei den Methodenaufrufen. Im Outputstream erwarte ich einen String. Kommt ein String an so ist der erste Parameter, durch Tab getrennt, die Methode und weitere Parameter sind die Variablen. Das wird in der Proxyklasse ausgelesen und dann ausgeführt.

Nur wie realisiere ich das für ein bestimmtes Object am besten? Klar es wird ein Object übergeben und mittels String kann ich mitteilen wie das Object zu handhaben ist und evt eine Methodenaufruf mitgeben.

Die Reihenfolge wäre dann wie folgt. Client übergibt ein Object mittels ObjectStream. Ist dieser angekommen muss der Server dieses Object "halten" un-zwar solange bis weitere Anweisungen über den normalen Stream reinkommt.

Ich hoffe ich konnte so in etwa mein Gedankengang verständlich rüberbringen.

Was ist von diesem Vorgehen zu halten?

Freue mich auf die ersten Antworten.


----------



## RelaX (26. Nov 2013)

Keiner eine Meinung dazu? Klar mit InstanceOf kann ich prüfen um welche Klasse es sich handelt.

Aber ich würde ja so nichts anderes "simulieren" wie die Funktionalität von rmi nur mit dem Unterschied das ich einen zusätzlichen Aufwand betreiben muss um den String zu interpretieren.

Gute Idee oder schlechte Idee?


----------



## anti-held (26. Nov 2013)

Verstehe ich das richtig?
Du willst einen Server haben, der per Socket ein Objekt erhält und dann einen String in dem die Methode steht, die der Server dann
auf diesem Objekt aufrufen soll?


----------



## RelaX (26. Nov 2013)

Genau. So in der Art hab ich mir das vorgestellt.

Nehmen wir einfach mal an es handelt sich um ein Chatprogramm neben einem Blog usw.

Hier mal kurz die Architektur so wie ich mir das in etwa ausgemalt habe.

Ich sende jetzt ein Objekt. Dieses Objekt besteht aus einem Blogeintrag mit allem was dazugehört.

Also Blogeintrag-object mit Bildern Links usw. schicke ich nun per Objectstream an den Server.
Dannach wird ein String geschickt = Blog \t Eintrag \t neu

Proxy macht folgendes:

Nimm String und schau folgende Möglichkeiten:

Chat? Dann weiter zu Chatproxyklasse

Blog? Dann weiter zu Blogproxyklasse. <--- in dem Beispiel ist das der Fall.

Blogproxyklasse macht folgendes:

Für Eintrag rufe diese Methode auf.

Das wars dann auch. Im Proxy stehen sogenannte Teilprojekte die zuerst außeinandergehalten werden. Das wäre selbst bei größeren Projekten dann kein so großes Problem mehr.


----------



## anti-held (26. Nov 2013)

Dann würde ich ein eigenes Persistance-Projekt machen

Dort kommen alle Entitys rein (z.B. Blog, Chat)

Dieses Projekt bindest du in deinen Server und deinen Client ein.

Dein Client sendet ganz normal dann die Objekte (Blog oder Chat)

Der Server verarbeitet die dann folgendermaßen:


```
try{
			Socket socket = new ServerSocket(8000).accept();
			ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
			Object obj = ois.readObject();
			if(obj instanceof Blog){
				((Blog) obj).method();
			} else if(obj instanceof Chat){
				((Chat) obj).method();
			} else {
				throw new ClassNotFoundException(obj.getClass().getCanonicalName());
			}
		}catch(Exception ex){
			// Exceptionhandling
		}
```

natürlich mit Schleife etc.


----------



## RelaX (26. Nov 2013)

Das wäre mein erster Ansatz gewesen. Jetzt hab ich bei der InstanceOf-Methode nur das Problem das ich nur eine Methode pro Klasse habe die ich aufrufen kann. Eine weitere Möglichkeit wäre dann ja zu jeder Klasse einen String zu setzen.


```
class Chat {
    private String Anweisung;

    .....

}
```

Vor dem übertragen setze ich den String und prüfe dann in der Methode der Klasse die möglichen Operationen und welche die jetzt ausgeführt werden soll. Nachteil hier ist das ich da keine Prarameter mitgeben kann, es sei denn ich setze diese in das Objekt und übergebe diese mit.


```
class Transporter {

   private Object obj;
   private Object parameter; // kann vom Typ auch ein Array oder sonst was sein.

.....
   public Object getObject() {
      return obj;
   }

}
```

Dann wäre das mit deinem Vorschlag soetwas:


```
try{
            Socket socket = new ServerSocket(8000).accept();
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            Transporter trans = (Transporter)ois.readObject();
            if(trans.getObject() instanceof Blog){
                ((Blog) trans.getObject()).method();
            } else if(trans.getObject()instanceof Chat){
                ((Chat) trans.getObject()).method();
            } else {
                throw new ClassNotFoundException(trans.getObject().getClass().getCanonicalName());
            }
        }catch(Exception ex){
            // Exceptionhandling
        }
```

Hab ich das so richtig verstanden?


----------



## anti-held (26. Nov 2013)

Was wäre denn ein Beispiel, dass du verschiedene Methoden einer Klasse (z.B. Blog) aufrufen müsstest?
Sollte das Verfahren mit diesem Objekt nicht immer gleich ablaufen?


----------



## RelaX (26. Nov 2013)

Nein leider nicht. Ein Beispiel wäre z.b. eine Änderung. Ich nehme mir einen Eintrag vom Server. Dieser wird dann bearbeitet und dann zurückgeschickt. Anderes Beispiel. Ich habe ein Input als Object welches ich verwende um es auf einer Seite darzustellen. Dieses Object kann jetzt ein Bild, ein Text oder sonst was sein. Bilder können aber auch noch anders verwendet werden. Z.b. wenn ein Chatter ein Bild hochladen möchte.

Ich sehe da das Problem das ich nachher für jede Funktion eine eigene Klasse schreiben muss damit die Übertragung zugeordnet werden kann.


----------



## RelaX (27. Nov 2013)

Aber ich denke es ist mittlerweile klar geworden wie ich so ein Problem angehen könnte.

Vielen Dank nochmal.


----------



## anti-held (27. Nov 2013)

Du kannst dir für alle verschiedenen Möglichkeiten, die du hast Objekte anlegen.

z.B. ein ChangePicDto, das das Bild und den Nutzernamen enthält.
Was du aber mit diesem Bild und Nutzernamen machst, sollte dein Server implementieren und nicht in
einer Methode auf dem Client beschrieben werden.

Dein Code könnte dann so aussehen:


```
if(obj instanceof ChangePicDto){
                changePic((ChangePicDto) obj);
            } else if(obj instanceof CreateBlogDto){
                createBlog((CreateBlogDto) obj);
            } else if(...){
                ...
            } else {
                throw new ClassNotFoundException(trans.getObject().getClass().getCanonicalName());
            }
```

und dann kannst du am Server deine changePic(), createBlog(), etc -Methoden implementieren.
Die Dtos enthalten halt immer die erforderlichen Objekte für die Aktion, die der Server ausführen soll.


----------



## RelaX (27. Nov 2013)

Ok vielen Dank. Ich hab das jetzt so gelöst:


```
public interface ChatEvent extends Serializable {

	String getMessage();
	
	String getUsername();

}
```

Wenn ich dann eine bestimmte Option brauche dann erschaffe ich mir einfach ein neues Event welches das interface ChatEvent implementiert.

So kann ich dann im Proxy mit folgendem die Sache ganz gut in den Griff bekommen:


```
public void executeTransfer(Object o) {
		if(o instanceof ChatEvent) {
			chatProxy.executeChat(o);
			
		} else if(o instanceof EngineEvent ) {
			engineProxy.executeEngine(o);
		}
	}
```

So kann ich verschiedene Proxyklassen schreiben und bleibe immer sehr flexible.


----------

