# Konzeptionelle Ausarbeitung einer synchronen Kommunkation (Server/Client))



## Pithecanthropus (9. Jun 2009)

"hello world!"  

Ich mache mir im Moment darüber Gedanken, wie ich die grundsätzliche synchrone Kommunikation zwischen dem Server und dem Client programmiere.

Das heißt, es soll nicht einfach ein klassisches Request/Reply Ding werden, sondern es soll auch vom Server Anfragen bzw. Anweisungen bekommen können. Es gibt also immer 2 Arten von Incoming Objects: einmal die Antworten vom Server und einmal Serveranfragen. Wenn ich jetzt lokal irgendwo ein Request an den Server schicke, dann muss ich auch mit 
	
	
	
	





```
new ObjectInputStream().readObject()
```
 auf eine Antwort warten.

Aber wie kann ich jetzt unterscheiden, ob es sich um eine Antwort oder um eine Anfrage des Servers handelt? Per se kann ich anhand des Objektes natürlich schon unterscheiden, was der Server nun will, aber soll ich jedes mal nach einem readObject() abfragen, ob es das oder das ist?... kennt jmd. vll. eine elegante und pfiffige Lösung.


----------



## tuxedo (9. Jun 2009)

Elegante Lösung? RMI, SIMON und Konsorten ...

"Eigene Lösung": Ein Protokoll entwickeln. 

Du könntest alle Objekte mit einem Basisinterface versehen, mit welchem man Informationen zum Objekt erfragen kann.

Bsp:


```
public interface BasisMessageObject {

public void MyTypeEnum getType();

}
```

Dann kannst du alle Objekte erstmal nach "BasisMessageObject" casten, damit dann nach dem genaueren Typ fragen, und dann anhand des Typs in das eigentliche Interface casten. 

Um das "Abfragen" kommst du nicht wirklich drum rum. Natürlich gibts auch noch andere vorangehensweisen. Du könntest VOR dem eigenltichen Objekt auch einen Integer schicken (Data*Stream), welcher dann deinen Objekt-Typ identifiziert.

Aber generell gilt: Immer alles serialisieren und casten ist nicht gut/schnell. SIMON und RMI haben da eine etwas verfeinerte Technik. 

Bei Spielen ist es wohl besten, ganz auf Serialisierung zu verzichen und ein Binäres Protokoll aufzusetzen. Das spart Bandbreite und ist sehr schnell.

Bei klassischen Client/Server Desktopanwendungen würde ich sowas wie RMI oder SIMON einsetzen. Denn wozu das Rad nochmal neu erfinden?

- Alex


----------



## Pithecanthropus (9. Jun 2009)

Das wird wohl eine eigene Lösung werden, da "vieles" bereits vorhanden ist. Das Interface z.B. existiert bereits bei mir als BasisProtokollKlasse und je nach Zweck leitet eine Klasse von der BasisProtokollKlasse ab, wobei die Idee mit dem Interface vll. besser wäre..?!?

Ich werde erstmal versuchen es auf diese Weise zu implementieren:  Jedes mal, wenn in einem GUI-Element eine Serveranfrage "ausgelöst" wird, wird eine synchronized sendObject() Methode aufgerufen, die erstmal generisch das passende ProtokollObjekt bastelt und verschickt und dann auch auf die Antwort wartet.. Wenn die Antwort zufällig keine Antwort, sondern eine Servernachricht (oder so) ist, wird das Objekt weitergeleitet (wo es hin soll) und sendObject() wartet dann weiter auf die Antwort.... ne Laufnummer hat das Protokoll auch schon, falls eine eindeutige Identifikation gebraucht wird.

Und nebenläufig läuft ein Thread der auf Serveranfragen wartet, falls mal sendObject() nicht läuft. ... Ich hoffe es klappt.. dürfte einige Zeit dauern.



> Denn wozu das Rad nochmal neu erfinden?



aus Spass.


----------



## tuxedo (9. Jun 2009)

Würde das etwas anders angehen, zumindest von der Struktur her:

Ich würde eine zentrale Empfangsinstanz machen. Also einen Thread, der nix anderes tut als Objekte empfangen, jedes empfangene Objekt grob zu betrachten und dann zu entscheiden was damit zu tun ist.

Wenn du wie du sagst bereits eine Laufnummer hast, ist die Ideal um die Objekte entsprechend zuzuordnen.

Wird eine Serveranfrage ausgelöst wird das entsprechende Anfrageobjekt versendet. Der Methodenaufruf ist dann aber noch nciht zuende... Die Methode "schläft" (wait-Mechanismus) bis der Empfangsthread etwas empfangen hat was eine Antwort ist. Wen der Empfangsthread "wecken" (notify) muss, ergibt sich aus der Laufnummer und dem Objekttyp.

So in der Art ist auch SIMON intern aufgebaut....

- Alex


----------



## Pithecanthropus (9. Jun 2009)

Könntest du dir vorstellen, dass der oben von mir beschriebene Ansatz funktioniert (nicht das ich mich da verrenne).
also die zentrale Empfangsinstanz hab ich mehr oder weniger auch... nur das es nicht möglich sein dürfte, dass dieser Thread ein Reply bekommt, weil das Warten auf so einen Reply mutual exclusive in der Methode sendObject wäre. Dadurch bräuchte ich auch kein Wait() oder notify(), da die Funktion new ObjectInputStream().readObject() solange wartet bis die Antwort kommt........:bloed:

dann würde doch das ganze Programm stehen bleiben, bis das Object angekommen ist ? Dann lass ichs lieber.

Der Ansatz von SIMON klingt vielversprechend.Kennst du zufällig die Klasse (vll. ungefähre Stelle) wo die 
Empfangsinstanz ein notify macht und eine Stelle, wo exemplarisch eine Methode ein wait() ausführt...so dass ich das direkt :rtfm: kann..., also die Interaktion nachvollziehen kann?


----------



## tuxedo (9. Jun 2009)

Dein Ansatz hört sich so an, als ob da viel zu viel synchronisiert wird und am Ende nicht "schnell" ist. Ist aber nur so'n Bauchgefühl.

Die "Empfängerklasse" in SIMON ist die Klasse "Dispatcher". Da gibt es eine Methode die eingehende Nachrichten entgegen nimmt.

Die Nachricht wird dann in einen ProcessorPool geworfen wie sie analysiert und weitergereicht wird. Ein Pool deshlab, damit bereits die nächste Nachricht gelesen werden kann. 

Jede ausgehende Nachricht hat einen "Monitor" der zum schlafen und wecken genutzt wird. Eine eingehende Antwort wird anhand der Sequenz-ID zum wecken des Monitors genutzt. Der geweckte Methodenaufruf holt sich dann in einer Result-Liste SEIN Result ab.

Fertig.

- Alex


----------



## Pithecanthropus (9. Jun 2009)

Danke für die Tipps. Damit kann ich bestimmt was anfangen...


----------

