Projekt WS05/06 – SS06
Erstellung eines Unterwasser Ökosystems
- Das Grobdesign -
Projektteilnehmer: Jens Böckel
Richard Woldert Vetiola Elezkurtaj Marco Becherer Roman Sauber
Kornelia Markovic Daniel Weber
Versionierung
Wann wurde
geändert?
Wer hat geändert?
Version Was wurde geändert?
15.11.2005 MB 1 Neu erstellt 22.11.2005 MB 1.1 Einleitender Teil eingeführt 22.11.2005 MB 1.2 Experiment mit Hierarchie-Tiefe 12.12.2005 MB 2.0 Inhaltsangabe und Diagramme eingefügt 13.12.2005 MB 2.1 Fisch: Diagramme aktualisiert 20.12.2005 MB 2.2 Bildnummerierung eingefügt 23.12.2005 MB 2.3 Aquarium: Diagramme aktualisiert 12.01.2006 RS 2.4 Fischteil überarbeitet 16.01.2006 KM 2.5 Aquarium überarbeitet 17.01.2006 JB 2.6 View und Controller eingefügt 21.03.2006 MB 3.0 ? 22.03.2006 MB 3.1 P2P aktualisiert 25.03.2006 MB 3.2 Änderungen von JB durchgeführt
Inhaltsangabe
1 Das Design des Ökosystems......................................................................................................................- 5 - 2 Die Komponenten des Ökosystems ...........................................................................................................- 5 - 3 View und Controller ..................................................................................................................................- 6 -
3.1 Das MVC-Pattern.............................................................................................................................- 6 - 3.2 Zusammenspiel beim starten............................................................................................................- 6 - 3.3 Features............................................................................................................................................- 6 - 3.4 Window Layout ...............................................................................................................................- 7 - 3.5 Interaktionen ....................................................................................................................................- 8 - 3.6 Elemente der View...........................................................................................................................- 8 - 3.7 Elemente des Controllers .................................................................................................................- 8 - 3.8 Pseudocode des Controllers .............................................................................................................- 9 -
4 Das Aquarium..........................................................................................................................................- 11 - 4.1 Datenstruktur bzw. Fischliste.........................................................................................................- 11 - 4.2 Initialisierung des Aquariums ........................................................................................................- 11 - 4.3 Schnittstellen zwischen Aquarium und P2P bzw. Fisch ................................................................- 11 - 4.4 Szenarien........................................................................................................................................- 12 -
4.4.1 handoff .................................................................................................................................- 12 - 4.4.2 sensing vom Fisch ................................................................................................................- 13 - 4.4.3 Kinder erzeugen ...................................................................................................................- 15 - 4.4.4 sensing vom Aquarium.........................................................................................................- 15 - 4.4.5 receiveInfo und sendInfo ......................................................................................................- 15 - 4.4.6 Fisch erreicht Aquariumsgrenze...........................................................................................- 16 - 4.4.7 refresh...................................................................................................................................- 18 -
4.5 GUI-Schnittstellen: Fisch aussetzen und angeln............................................................................- 18 - 5 Die Fische................................................................................................................................................- 19 -
5.1 Einleitung.......................................................................................................................................- 19 - 5.1.1 Bewegung.............................................................................................................................- 19 - 5.1.2 Fischarten .............................................................................................................................- 19 - 5.1.3 Grafische Realisierung der Fische........................................................................................- 20 -
5.2 Daten..............................................................................................................................................- 20 - 5.3 Verhalten........................................................................................................................................- 20 -
5.3.1 run()-Methode ......................................................................................................................- 20 - 5.3.2 update().................................................................................................................................- 21 - 5.3.3 sense() - Erfassen der Umgebung.........................................................................................- 21 - 5.3.4 act().......................................................................................................................................- 21 - 5.3.5 refresh() ................................................................................................................................- 25 -
5.4 Schnittstellen zu den anderen Anwendungsschichten....................................................................- 25 - 5.4.1 Fisch � Fisch.......................................................................................................................- 25 - 5.4.2 Fisch � Aquarium ...............................................................................................................- 26 - 5.4.3 Fisch � P2P-Schicht............................................................................................................- 26 -
6 Die Peer-to-Peer Verbindung ..................................................................................................................- 27 - 6.1 Der P2P-Client ...............................................................................................................................- 27 -
6.1.1 Struktur des Client-Verbandes..............................................................................................- 27 - 6.1.2 Zyklus eine P2PClients.........................................................................................................- 27 - 6.1.3 Grober Ablauf eines Joins eines neuen Clients....................................................................- 27 - 6.1.4 Zyklen des verbundenen Clients / Schnittstellen..................................................................- 32 - 6.1.5 Client Crash..........................................................................................................................- 34 -
6.2 Der P2P-Server ..............................................................................................................................- 35 - 6.2.1 Aufgaben des P2PServers.....................................................................................................- 35 - 6.2.2 Szenarien ..............................................................................................................................- 36 - 6.2.3 Schnittstellen ........................................................................................................................- 38 -
- 5 -
1 Das Design des Ökosystems
Ein Unterwasser-Ökosystem bietet ein interessantes Gebiet für die Ausarbeitung in einem Informatik-Projekt.
Hier bei spielen verschiedene Komponenten mit um einen Gesamtleben zu realisieren. Auf diese Komponenten
wird im Kapitel 1.1 näher eingegangen. In einem solch komplexen Ökosystem existiert eine Vielzahl von
Abläufen, Reaktionen und Funktionen.
Das Ökosystem ist deswegen so komplex, da viele Abläufe in einander greifen und somit gegenseitig abhängig
sind. Diese Komplexität zeigt sich daran, dass bei einer Änderung eines Faktor, bzw. weglassen einer
Eigenschaft viele andere Dinge betroffen sind. Ein Beispiel hier für ist die Frage, ob Fische in unserem
Ökosystem ein natürlich begrenztes Leben haben sollen, bzw. ob die kleinen Fische irgendwann auch
verhungern können, wenn zu viele der kleinen Fische vorhanden sind. Wie wird in einem solchen Fall die
Nahrung im Aquarium gesteuert? Dies wirft dann auch gleich die Frage auf, was passiert in unserem Ökosystem,
wenn die kleinen Fische verhungert sind? Fallen dann die großen Fische übereinander her? Was löst dann dieses
Fressverhalten aus?
2 Die Komponenten des Ökosystems
Die Komponenten dieses Ökosystems werden kurz anhand des folgenden Bildes beschrieben. In diesem Bild
wird deutlich, dass jeder Peer(Client) sein eigenes Aquarium darstellt mit einer gewissen Anzahl von Fischen.
Die Fische sind aber nicht
auf ihr Aquarium
beschränkt, sondern
können sich frei bewegen
innerhalb der ihnen
gesetzten Möglichkeiten.
So kann z.B. ein gelber
Fisch (gelber Pfeil) über
die P2P-Verbindung in ein
anderes Aquarium
schwimmen. Im gleichen
Sinn kann auch ein anderer
Fisch (violetter Pfeil) in
ein anderes Aquarium
übergehen. Im folgenden
werden die einzelnen
Komponenten genauer
beschrieben und deren Design dargestellt.
Abbildung 2-1 Grobe Skizze Aquarium
- 6 -
3 View und Controller
3.1 Das MVC-Pattern
Das Programm ist nach dem MVC-Prinzip aufgebaut, d.h. die Komponenten sind nochmals getrennt in ein
Model, eine View und ein Controller.
Die Komponente View enthält alle notwendigen Klassen um die Benutzersicht, z.B. die GUI, darzustellen. Sie
sollte keine Elemente haben, die eine Kontrolle ausüben bzw. eine Logik (Model) enthalten. Der Controller
hingegen enthält alle Elemente zur Kontrolle der View und der Logik (Model). Der Controller stellt die
Verbindung oder auch Schnittstelle zur Logik (Model) dar. Das Model ist für die Logik des Programms
zuständig. Das Model (Logik) kümmert sich um die Bewegung der Fische, ihr Verhalten, Nahrungszufuhr usw.
3.2 Zusammenspiel beim starten
Ein Benutzer startet das Programm. Der Controller instanziert nun die P2P-Verbindung und die View. Die View
stellt die grafische Verbindung (GUI) zwischen dem System und dem Benutzer dar. Der Benutzer hat über die
Maus die Möglichkeit in Fenstern verschiedene Elemente zu bedienen, z.B. Fische entfernen. Ein solches Signal
ird vom Controller aufgefangen und weiterverarbeitet.
In der View selber wird nun das Aquarium instanziert und alle notwendigen Fenster erstellt. Die Klasse
Observer, in der View, hat einen Blick auf alle Fische und kümmert sich um deren updates.
3.3 Features
View:
Aquariumsicht
Übersicht über die Aquarien auf den Nachbarclients
Überblick über die Position im Verband
Show origin of fish
Aquariumringfenster
Darstellung der Fischbewegungen
Controller:
Menü mit Einstellungen, Aktionen und Hilfe
Catch fish
Insert fish
- 7 -
Fischeditor Aufruf
Exit Aufruf
Help window Aufruf
Einstellungsfenster öffnen
Aquariumringfenster öffnen
3.4 Window Layout
Typisches Windows Layout mit Menüzeile und Sichtfenster für das eigene Aquarium. Die Nachbarclients
werden als kleine Rechtecke am oberen rechten Rand transparent eingeblendet. Deren Fische werden als
Pixelpunkte dargestellt. Der Gesamtüberblick über alle Aquarien kann als eigenes Fenster über das Menü
geöffnet werden. Die Herkunft der Informationen ist von dem P2PServer.
Abbildung 3-1 Window layout
- 8 -
3.5 Interaktionen
Die Hilfe, das Einstellungsfenster und der Konfigurationseditor für neue Fische werden über das Menü
aufgerufen. Außerdem sind das Einsetzen eines Fisches und das Angeln eines Fisches über das Menü zu
erreichen.
Die interaktiven Möglichkeiten in der Aquariensicht sind Fisch Angeln (catch fish) und Fisch einsetzen (Insert
fish) und Details zu einzelnen Fischen einblenden zu lassen. Damit ist es möglich Fische herauszunehmen und
wieder einzusetzen.
Die Details eines Fisches (Herkunftsland, Name, Art) werden transparent eingeblendet wenn mit der Maus
„drüber gefahren“ wird.
3.6 Elemente der View
Zur View gehören das Hauptfenster ohne Menüzeile, die Hauptsicht, die beiden Nachbarschirme, das
Hilfefenster, der Preferenceseditor und der Fischeditor.
Die View stellt diese nur da. Im Hauptfenster bewegen sich die lokalen Fische frei. Die Animation der
Schwimmbewegung wird durch animierte Gifs gelöst. Die Animation der Streckenbewegung der Fische erledigt
die View selbst. Dazu pollt die View die Daten (Postionen der Fische) des Aquariums regelmässig und zeichnet
die Positionsdifferenz zwischen aktuellem und letzten Stand als Animation.
3.7 Elemente des Controllers
Der Controller besteht aus dem graphischen Element Menü und dem logischen Baustein, der die unten stehenden
Aktionen durchführt.
Der Controller wird als (Event)Listener designed, der alle interaktiven Events wie Tastatureingaben,
Mausbewegungen und -klicks und Menüaufrufe abfängt. Auf diese Events reagiert der Controller, indem er die
entsprechenden Methoden der GUI (Hilfefenster, Überblicksfenster, Preference Window, Fish Editor Fenster,
Window schliessen), des Aquariums (Fisch einsetzen, angeln) und des P2PClients (Verbinden, Trennen) aufruft.
- 9 -
3.8 Pseudocode des Controllers
controllerEvent (event)
{
switch (event)
case „helpWindow“:
gUI.showHelpWindow();
case „showAquariumRing“:
gUI.showAquariumRing ();
case „preferencesWindow“:
gUI.showPreferencesWindow();
case „showFishEditor“:
gUI.showFishEditor();
case „exit“:
gUI.closeWindow();
p2PClient.logoff();
System.exit();
case „logoff“:
p2PClient.logoff();
case „connect“:
p2PClient.connect();
case „catchFish“:
- 10 -
aquarium.catchFish(GUI.getMousePosition());
case „insertFish“:
aquarium.insertFish(GUI.getNewFish());
default:
donothing;
}
- 11 -
4 Das Aquarium
Das Aquarium ist eine Ansammlung von Listenern, d.h. es reagiert auf Nachrichten und äußere Einflüsse.
Hauptaufgabe besteht im Instanziieren von Objekten und dem Erzeugen eines Threads dafür. Die Threads dürfen
nicht im Konstruktor erzeugt werden, da dort kein Exception-Handling möglich ist.
Das Aquarium verwaltet die absoluten Koordinaten des Fisches pro Aquarium, der Fisch selbst arbeitet nur mit
relativen Koordinaten.
4.1 Datenstruktur bzw. Fischliste
Die Fischliste ist ein Vektor aus Fischobjekten. Die Fischobjekte enthalten die Fischeigenschaften, wie zum
Beispiel Art, Geschlecht, und die aktuelle Position des Fisches im Aquarium. Dieser Vektor wird durch die
refresh () -, sendInfo () - und receiveInfo ()- Methoden auf dem laufenden gehalten. Dabei befinden sich in dem
Vektor auch Fischobjekte aus Nachbaraquarien; dies ist für die sense () - Methode wichtig.
4.2 Initialisierung des Aquariums
Im Konstruktor wird die interne Datenstruktur Fischliste erzeugt, ebenso eine vorkonfigurierte Menge an
Fischen. Für jeden Fisch wird dann ein eigener Thread gestartet. Die Fischliste wird aktualisiert und
anschließend wird die Kontrolle an das Fenster-System übergeben.
4.3 Schnittstellen zwischen Aquarium und P2P bzw. Fisch
(Die Pfeile sind benutzt-Beziehungen)
Abbildung 4-1 Schnittstellen allgemein
- 12 -
Methodensammlung: Schnittstellen
refresh ()
sense ()
createChildren ()
receiveFish ()
receiveInfo ()
sendInfo ()
insertFish ()
grabFish ()
4.4 Szenarien
4.4.1 handoff
Regelt den Fischtransfer. P2P Klasse ruft die receiveFish () Methode des Aquariums auf, um den Fisch zu
übergeben. Die setFish () Methode bedeutet, dass der Fisch in die FishListe eingetragen wird.
Abbildung 4-2 handoff
- 13 -
Das Aquarium ruft hier die Methode sendFish () der P2P Klasse auf, um den Fisch zu übersenden.
4.4.2 sensing vom Fisch
Methode, die vom Fisch aufgerufen wird. Liefert dem Fisch die Information über seine Umgebung, d.h. andere
Fische. Wichtig dabei ist, dass dabei zwei Abstände beachtet werden:
• absolute Sichtweite X: Bereich, wieweit der Fisch überhaupt sehen kann
• unscharfe Sichtweite Y: Bereich, ab dem der Fisch nur noch „Umrisse“ wahrnimmt, d.h. er erkennt nur
noch das Vorhandensein anderer Fische, aber keine Details.
Die Datenstruktur Fischliste (in der Abbildung INFO genannt) ist die Klasse FischListe
Abbildung 4-3 Vorgang "Sensing Fisch"
- 14 -
Abbildung 4-4 Vorgang Aufruf "Methode sense()"
- 15 -
4.4.3 Kinder erzeugen
4.4.4 sensing vom Aquarium
Tauscht für das sensing der Fische notwendige Informationen zwischen Nachbar-Aquarien aus und tauscht diese
mit Hilfe der P2P-Klasse aus. Ausgetauschte Information: alle Objekte in einem Bereich mit Koordinaten und
restlichen Zustand.
4.4.5 receiveInfo und sendInfo
Zwei Methoden, die von P2P genutzt werden. Sie versorgen die Fischlisten-Datenstruktur (FishListe) mit
Informationen aus Nachbaraquarien. Sie bilden damit einen weiteren Baustein in der Grundlage für das sensing
der Fische (sense ()).
Abbildung 4-5 Vorgang Paarung
- 16 -
4.4.6 Fisch erreicht Aquariumsgrenze
Abbildung 4-7 Für Sensing relevante Bereiche
Abbildung 4-6 Infos einholen
- 17 -
Der Fisch ist also an seiner Umgebung interessiert; damit das Aquarium 2 ihm die erforderliche Information
darüber geben kann, muss es zuvor die fehlenden Daten vom Aquarium 1 erhalten haben.
Dieser Datenaustausch ist die Aufgabe dieser beiden Methoden (receiveInfo, sendInfo). Dabei bleibt es der P2P-
Komponente überlassen, für den zeitlichen Ablauf bzw. die Aktualität zu sorgen; und dafür, dass nur Daten
zwischen tatsächlichen Nachbaraquarien ausgetauscht werden.
Abbildung 4-8 Aktion, wenn Fische Aquarium-Grenzen erreicht
Abbildung 4-9 Fisch einsetzen
- 18 -
4.4.7 refresh
Fisch ruft refresh des Aquariums auf und übergibt seine Parameter. Daraufhin aktualisiert das Aquarium die
Fischliste und benachrichtigt die view, dass Änderungen passiert sind (via notify () Methode im Observer-
Pattern).
Parameter: Art, Geschlecht, Positionsänderung/vektor
4.5 GUI-Schnittstellen: Fisch aussetzen und angeln
Die Methode grabFish () erhält Koordinaten (von view bestimmt) und löscht dann das Fischobjekt aus der
Fischliste, welches sich an diesen Koordinaten befindet.
Abbildung 4-1 Angeln eines Fisches
- 19 -
5 Die Fische
5.1 Einleitung
Die Fische sind intelligente Agenten, d. h. sie sind in der Lage mit ihrer Umwelt, dem Aquarium, zu
kommunizieren. Dies bedeutet, dass sie Entscheidungen treffen können und sollen, und mit ihrer Umwelt
interagieren müssen. Dazu dient das Aquarium als „Radar“, welches einem anfragenden Fisch Auskunft über
seine nächsten Nachbarn gibt.
Anforderungen an die Fische:
- Die Fische sollen sich in alle Richtungen bewegen können.
- Die Fische sollen mit dem Aquarium kommunizieren können. Dadurch erhalten sie eine
„Radarfunktion“.
- Die Fische haben eine Energiebilanz. Diese soll, wie ihr natürliches Vorbild, dafür sorgen, dass
schwache Fische nicht mehr entkommen können und dient der natürlichen Selektion. Diese
Energiebilanz kann auch wieder verbessert werden, wenn die Fische entsprechend Nahrung
aufnehmen.
- Die Fische sollen sich vermehren und gefressen werden können. Dies läuft über Kommunikation
direkt mit den anderen Fischen im Aquarium.
5.1.1 Bewegung
Der Bewegungsablauf der Fische sollte möglichst natürlich und fließend sein. Dabei können sie sich auf einer
zweidimensionalen Ebene frei bewegen. D.h. die Fische bewegen sich parallel zum Bildschirm. Die Fische
sollen sich umdrehen können. Die Geschwindigkeit der Fische ist unterschiedlich.
5.1.2 Fischarten
Die Fischarten unterscheiden sich allgemein in Farbe, Größe, Schwimmgeschwindigkeit und Form.
Es gibt männliche und weibliche Fische. Dabei unterscheiden sich Männchen und Weibchen in ihrem
Paarungsverhalten: Die Männchen gehen auf die Weibchen zu, die selbst nicht aktiv auf Partnersuche gehen,
sondern auf einen Partner warten.
Außerdem wird unterschieden zwischen zwei Typen von Fischen:
• Raubfische fressen und jagen andere Fische um ihren Energiehaushalt aufzufüllen und pflanzen sich bei
ausreichend Energie fort. Ihr Hunger und Sättigungsgefühl wird durch ihren Energiestand dargestellt.
• Vegetarier sind für andere Fische harmlos und sind ebenso bestrebt ihre Art zu erhalten indem sie sich
fortpflanzen. Sie erhalten aus Vereinfachungsgründen in jedem Tic eine kleine Menge Energie. Um
Energie aufnehmen zu können müssen sie schwimmen.
- 20 -
5.1.3 Grafische Realisierung der Fische
Im Treffen vom 20.12.2005 wurde in allgemeiner Übereinstimmung beschlossen die Fische auf 2-dimensionaler
Basis im Comicstil darzustellen. Genaueres wird noch festgelegt. Bei Übernahme von fremden Grafiken muss
beachtet werden, dass keine Copyright-Rechte verletzt werden.
5.2 Daten
Größe {klein, mittel, groß}
Schwimmgeschwindigkeit {sehr langsam, langsam, mitt el, schnell, sehr schnell}
Sichtweite // konstant für alle Fische
Geschlecht {männlich, weiblich}
Fischtyp {Raubfisch, Vegetarier}
Name : String
Energie : Integer
Grafik // grafische Darstellung des Fischs (z.B. jp g-File)
5.3 Verhalten
5.3.1 run()-Methode
Das Leben eines Fisches findet innerhalb einer
Endlosschleife statt. Beim Erzeugen eines neuen
Fischs wird vom Aquarium ein neuer Thread
erzeugt, der die run()-Methode ausführt.
Beim Tod bzw. Gefressenwerden wird der Fisch
über den Aufruf seiner Methode terminieren()
getötet. Das Aquarium wird mit einem letzten
Aufruf der Methode refresh() informiert.
Abbildung 5-1Zyklus des Fisches
- 21 -
5.3.1.1 Pseudocode:
while(true) {
update();
sense();
act();
refresh();
}
5.3.2 update()
Aktualisieren der Fisch-internen Daten. Z.B. Aktualisieren der Energiebilanz.
5.3.3 sense() - Erfassen der Umgebung
Die Fische sollen nicht alles sehen bzw. alles wissen über das Aquarium. Die Sichtweite („Radarreichweite“) ist
beschränkt. Interessant wäre eine unterschiedliche Sichtweite der Fische, aber aus Gleichgewichtsgründen sollte
die Sichtweite aller Fische gleich sein.
Als Beispiel: Wenn ein Jagdfisch weiter sieht als ein gejagter Fisch dann hat der Gejagte keine Chance zu
entkommen. Umgekehrt wenn der kleine Fisch weiter sieht als ein großer dann schwimmt der kleine Fisch weg
bevor der große ihm gesehen hat.
5.3.4 act()
Diese Methode steuert das Verhalten der Fische.
Oberste Priorität ist Gefahren erkennen egal wie der Energiestatus ist.
5.3.4.1 Entscheidungspfad
Die folgende Grafik stellt den Entscheidungspfad der Fische dar:
- 22 -
5.3.4.2 Zonenmodell
Um diesen Entscheidungspfad bei unklaren Situationen zu unterstützen können wir die unmittelbare Umgebung
des Fischs in Zonen einteilen und dann so – wenn eine eindeutige Entscheidung nicht möglich ist – über
Gewichtung der einzelnen Zonen eine Entscheidung finden:
Gefahr Neutral Neutral Neutral Fisch Nahrung Neutral Partner Neutral
Abbildung 5-2 Aktionen des Fisches für jeden "Tick"
- 23 -
Eine mögliche Einteilung der Zonen wäre:
- Neutral = keine Vor- oder Nachteile innerhalb dieser Zone zu erwarten
- Gefahr = ein Fressfeind lauert
- Nahrung = für Jagdfische ein viel versprechendes Gebiet
- Partner = ein potentieller Partner in diesem Gebiet bekannt
5.3.4.3 Entscheidungspfad in Pseudocode:
If (Gefahr) { Flüchten; } else { If (Energie ausreichend)
{ If (Partner für Paarung in Sicht) {
If (Partner in Paarungsdistanz) {
Paaren; } Else {
Annähern an Partner; }
} else {
Paarungsritual; }
} else
{ if (Futter in Sicht)
{ If (Futter in Fressreichtweite)
{ Fressen; } Else
{ Annähern an Opfer; } } else
{ Opfer suchen; } } }
- 24 -
5.3.4.4 Fressen
Wenn ein Jagdfisch ausreichend nahe an sein Opfer gelangt, sendet er ihm eine Nachricht bzw. ruft die Methode
terminieren() auf, und es erfolgt ein Energietransfer vom Opfer auf den Killer.
Durch einen letzten Aufruf des Opfers der Methode refresh() wird diese Information an das Aquarium
mitgeteilt und der Fisch entfernt.
5.3.4.5 Fortpflanzen
Fortpflanzen ist neben der Nahrungssuche die Lebensaufgabe der Fische. Beim Paaren müssen Männchen und
Weibchen der gleichen Fischart zusammentreffen und beide paarungsbereit sein.
Die männlichen Fische machen den Aufruf zur Paarung. Die weiblichen Fische warten auf einen Partner
während sie durch das Aquarium schwimmen.
Das Männchen kann die Anfrage zur Paarungsbereitschaft aus einer bestimmten Entfernung machen und
signalisiert somit dem Weibchen sein Interesse. Wenn das Weibchen paarungsbereit ist, bleibt es an der Stelle
stehen und wartet (eine bestimmte Zeit lang) auf das Männchen.
Eine Paarungsaufforderung kann vom Partner auch abgelehnt werden, wenn er in diesem Moment andere
Prioritäten hat, z.B. nicht genug Energie für eine Paarung besitzt und sich auf Nahrungssuche befindet.
Bei einer Abfuhr versucht das Männchen wieder im nächsten Tic einen Aufruf zur Paarung und verfolgt das
Weibchen. Diese Situation geht solange weiter bis entweder das Männchen nicht mehr genug Energie zur
Paarung hat und seine Priorität auf Fressen ändert, oder das Weibchen genug Energie zu einer Paarung hat.
Um zu Verhindern dass sich zwei Fische ohne Pause paaren wird eine „Paarungssperre“ realisiert durch das
Verbrauchen einer bestimmten Menge Energie beim Paaren, so dass nun die Nahrungssuche wieder wichtigstes
Ziel wird. Beim Paaren wird eine noch zu definierende Menge an Nachfahren erzeugt.
5.3.4.6 Erklärung der Methoden im Entscheidungspfad in Pseudocode
Methode Flüchten() { Bewegung weg vom Feind mit maximaler Geschwindigke it; } Paaren() { Kommunikation mit Partner aufbauen;
if (Partner.Paarungsbereitschaft) { Aquarium.createChildren() Energieabzug; } Else { Partner suchen(); } }
- 25 -
Paarungsritual()
{
Männliche Fische: Annähern an Weibchen
Weibliche Fische: Warten auf Männchen
}
Partner suchen() { Geradeaus weiter Schwimmen; } Fressen() { Nachricht an Opfer senden: „I will kill you!“; Opfer wird terminiert; Energietransfer von Opfer auf Killer; } Annähern an Opfer() { Maximale Geschwindigkeit Richtung Opfer; }
Opfer suchen() { Geradeaus weiter Schwimmen; }
5.3.5 refresh()
Der Fisch sendet seine Entscheidungsergebnisse an das Aquarium, d.h. ob er gefressen wurde, ob Kinder gezeugt
wurden, in welche Richtung er sich bewegt etc.
5.4 Schnittstellen zu den anderen Anwendungsschichten
5.4.1 Fisch � Fisch
5.4.1.1 terminieren()
Wird aufgerufen vom fressenden Fisch wenn er diesen Fisch frisst. Zurückgegeben wird die zu übertragende
Energie.
5.4.1.2 paarenmit()
Wird aufgerufen vom Partnerfisch als Aufforderung zur Paarung.
5.4.1.3 paarungsbereit()
Gibt zurück, ob der Fisch paarungsbereit ist.
- 26 -
5.4.2 Fisch � Aquarium
5.4.2.1 sense()
Der Fisch fordert vom Aquarium eine Liste der Objekte in seiner Umgebung an. Dabei müssen Informationen
wie Objekttyp und Entfernung, sowie Fischart, Geschlecht und Paarungsbereitschaft übermittelt werden.
5.4.2.2 refresh()
Übermittlung der Handlungsentscheidung an das Aquarium: Richtungsvektor.
5.4.3 Fisch � P2P-Schicht
Keine direkte Interaktion!
- 27 -
6 Die Peer-to-Peer Verbindung
6.1 Der P2P-Client
6.1.1 Struktur des Client-Verbandes
Innerhalb der Aquarium Gruppe (ähnlich wie ein Netzwerk Subnet) bilden die Clients eine Ringstruktur.
Benachbarte Peer-IDs (Jeder Client hat eine eindeutige ID = Peer ID) liegen nebeneinander. Damit der Ring
geschlossen ist, liegen die Clients mit der höchsten und der niedrigsten IDs nebeneinander.
6.1.2 Zyklus eine P2PClients
Im folgendem Diagramm ist der Lebenszyklus eines P2PClients dargestellt. Die einzelnen Abschnitte werden in
den Abschnitten C.) - E.) erklärt.
6.1.3 Grober Ablauf eines Joins eines neuen Clients
Als erstes wird die Aquarium Gruppe gesucht. Existiert sie nicht (kein andere Client vorhanden), wird sie mit
dem neuen Client automatisch erstellt. Der nun Mitglied gewordene Client verursacht bei gegebenfalls
vorhandenen Clients ein Event, auf das die anderen Clients mit dem Einbinden des neuen Clients reagieren.
Daraufhin bauen die nun neu miteinander verbundenen Clients (Nachbarn) Kommuniaktionskanäle auf.
Gruppe finden
Die Gruppe existiert mit dem ersten angemeldeten Client. Das Anmelden geschieht durch das Suchen nach der
Gruppe automatisch und benötigt keine weitere Erläuterung.
Join
Joined ein neuer Client in die Gruppe, reagiert der ClientListener mit der Abfrage, ob die neue PeerID eine
seiner NachbarIDs entspricht. Sollte das der Fall sein, schickt er dem neuen Client seine ID als neuen
entsprechenden Nachbarn. Der neue Client bestätigt den Empfang dieser Nachricht mit dem Versand einer
- 28 -
analogen Nachricht. Beide Clients setzen nach Erhalt der beiden Nachrichten die ID des anderen als
entsprechende NachbarID.
1. Fall: neuer Peer findet niemanden - setzt sich selbst als linken und rechten Nachbar:
Setze linken und rechten Nachbar:
If(firstInGroup==true)
{
setNewRightNeighbour (2);
setNewLeftNeighbour (2);
}
2. Fall: Peer (1) ist allein im „P2P-Ring“ und hat sich selbst als linken und rechten Nachbar:
Neuer linker und rechter Nachbar:
If(ownPeerID == rightPeerID && ownPeerID == leftPeerID)
{
setNewRightNeighbour (4);
setNewLeftNeighbour (4);
}
2 4
Nachher:
2
Vorher:
2
Nachher:
2 4
Vorher:
- 29 -
3. Fall: bei mindestens 2 Peers:
a) Einfügen in Mitte:
Neuer rechter Nachbar:
If(newPeerID > ownPeerID && newPeerID < rightPeerID)
{
setNewRightNeighbour(3);
}
Neuer linker Nachbar:
If(newPeerID < ownPeerID && newPeerID > leftPeerID)
{
setNewLeftNeighbour(3);
}
2 4
3
7
Vorher:
2 4
3
7
Nachher:
- 30 -
b) Einfügen am Ende:
Neuer rechter Nachbar:
If(newPeerID > ownPeerID && newPeerID > rightPeerID && rightPeerID < ownPeerID)
{
setNewRightNeighbour (9);
}
Neuer linker Nachbar:
If(newPeerID > ownPeerID && newPeerID > leftPeerID && leftPeerID > ownPeerID)
{
setNewLeftNeighbour (9);
}
c) Einfügen am Anfang:
9
2 4
7
Vorher:
9
2
4
7
Nachher:
1
2 4
7
Vorher:
1 4
7
2 Nachher:
- 31 -
Neuer rechter Nachbar:
If(newPeerID < ownPeerID && newPeerID < rightPeerID && rightPeerID < ownPeerID)
{
setNewRightNeighbour (1);
}
Neuer linker Nachbar:
If(newPeerID < ownPeerID && newPeerID < leftPeerID && leftPeerID > ownPeerID)
{
setNewLeftNeighbour (1);
}
Kommunikationskanäle aufbauen:
Zu jedem Nachbarn werden je zwei Kanäle erstellt. Einer wird zur Übermittlung zum regelmäßigen
Informationsaustausch zwischen den beiden Aquarien und zum Monitoring der Nachbarn benützt.
Der andere Kanal wird zum Austausch von Fischen und Nachbarschaftsmitteilungen verwendet.
- 32 -
6.1.4 Zyklen des verbundenen Clients / Schnittstellen
Der verbundene Client startet nun drei weitere Threads. Diese neuen und der bisher gestartete Thread reagieren
auf vier verschiedene Events. Diese Events werden von folgenden Bereichen ausgelöst:
Aquarium: P2PClient reagiert
Monitoring: regularPipeListener reagiert
join Requests: clientListener reagiert
neighbourMessages und FishTransfer: neighbourListener reagiert:
Auf Methodenaufruf vom P2PClient durch das Aquarium (sendFish) reagiert der P2PClient mit dem Transfer
der übergebenen Fisches zu dem angegebenen Nachbarn.
Der regularPipeListener besitzt jeweils einen Timer für einen Nachbarn. Sobald von dem Nachbarn eine
regularInfo eintrifft, beginnt der Timer von vorne zu zählen. Trifft keine Info ein, wird der Timer
heruntergezählt. Sollte n Mal keine Nachricht eintreffen, wird der Nachbar als dead deklariert. Dann öffnet der
Client eine BackupPipe, um die Lücke im Ring wieder zu schliessen. Dazu mehr im Kapitel E.)
Abbildung 6-1 Vorgang einer Fischsendung
- 33 -
Der clientListener reagiert auf Events, die von neuen Clients ausgelöst werden und führt die Schritte aus
Abschnitt C.) durch.
Meldet sich ein Client ab, schickt er seinen Nachbarn eine Message mit der ID des jeweils anderen Nachbarn,
analog zu Schritt 3.). Dieses Event wird von dem neighbourListener abgefangen. Der neighbourListener reagiert
außerdem auf einkommende Fische. Diese werden zu dem Aquariumobjekt weiter geleitet. Schnittstellen siehe
Aquarium Beschreibung
Abbildung 6-1 Sendung eines Fisches zu anderem Client
Abbildung 6-2 "Lauschen" nach neuen Clients
- 34 -
6.1.5 Client Crash
sollte ein Client unabgemeldet ausfallen, reagieren beide bisherige Nachbarn mit dem Ablauf des Timers der
beiden regularPipeListeners. Bei diesem Event sendet der linke Nachbar des crashed clients (ccs) dem rechten
Nachbarn des ccs wie bei C.)2.) eine Nachricht mit seiner eigenen ID als neuen linken Nachbarn. Der Kanal wird
durch die ID des ccs eindeutig definiert. Damit kann der Ring wieder geschlossen werden.
Abbildung 6-3 Neuer Nachbar setzen
Abbildung 6-4 Öffnen des Backup-Kanal
- 35 -
6.2 Der P2P-Server
6.2.1 Aufgaben des P2PServers
Der P2PServer soll folgende Funktionalität erfüllen:
Sammlung der Ringstrukturdaten (Clients)
optische Aufbereitung dieser Daten (lokal)
datentechnische Aufbereitung der Daten für Clientzugriffe
Der Server soll als Administrator Tool dienen, mit dem die Ringform des Clientverbundes dargestellt werden
kann. Etwaige Veränderungen im Ring sollen ebenfalls dargestellt werden.
Dazu registriert er sich bei einem Dienst der die Client Verbindung überwacht und wird dadurch zu einem stillen
„Zuhörer“ (Listener). Aus dieser Liste von verbundenen Clients erstellt der Server eine Datenstruktur, die dann
in eine Datei geschrieben wird.
Der Server läuft auf einem Webserver, damit die Clients diese Datei lesen können, und die P2PServer
Applikation dort als Applet abgerufen werden kann. Die Clients brauchen den Zugriff auf die Datei um ebenfalls
die Ringstruktur darstellen zu können.
Da die Darstellung auf den Clients ähnlich (identisch) mit der auf dem Server sein soll, kann sowohl auf dem
Server als auch auf dem Client der selbe Code verwendet werden.
Änderungen im Ring werden vom Server gepollt.
- 36 -
6.2.2 Szenarien
Server logt sich in die Gruppe ein:
Server registriert sich beim GroupService
Server()
{
GroupService.registerListener(server)
}
Abbildung 6-5 Ringübersicht
- 37 -
Server pollt RingService um die aktuellen Clients zu erhalten:
Server ruft beim GroupService eine Methode auf um die aktuell verbundenen Clients zu
erhalten
run()
{
while(true)
{
myPeers = GroupService.getConnectedPeers()
showRing(myPeers)
Thread.sleep(x ms)
}
}
Ring verändert sich:
Der bisherige Zustand des Rings wird animiert zum neuen Zustand übergeführt
showRing(peers)
{
if (peers != oldPeers)
animateRingChange(peers, oldPeers)
else
showCurRing(peers)
}
- 38 -
6.2.3 Schnittstellen
Die Schnittstellen zwischen Client und Server und Server und Ring werden über die Datei bzw. über den Service
erstellt. Zum Übermitteln der aktuellen Ringstruktur zu den Clients wird die Datei bereit gestellt und zur
Kenntnisnahme der Ringstruktur bzw. Deren Veränderungen wird der GroupService benützt.
Top Related