Compare commits
No commits in common. "c958cc6634073fbe2ca04899e469f8aa07998406" and "3cd8ca1d0d3f812101aa278048c269c756e738b0" have entirely different histories.
c958cc6634
...
3cd8ca1d0d
20
Code/Main.py
20
Code/Main.py
|
@ -11,7 +11,6 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Getting the args
|
Getting the args
|
||||||
- own ip
|
|
||||||
- own port
|
- own port
|
||||||
|
|
||||||
Optional: A neighbour:
|
Optional: A neighbour:
|
||||||
|
@ -23,25 +22,22 @@ if __name__ == "__main__":
|
||||||
args = sys.argv
|
args = sys.argv
|
||||||
|
|
||||||
print(args)
|
print(args)
|
||||||
if len(args) >= 3:
|
if len(args) >= 2:
|
||||||
own_ip = args[1]
|
own_port = int(args[1])
|
||||||
own_port = int(args[2])
|
|
||||||
else:
|
else:
|
||||||
print("using default ip 0.0.0.0")
|
|
||||||
print("using default port 8080")
|
print("using default port 8080")
|
||||||
own_ip = "0.0.0.0"
|
|
||||||
own_port = 8080
|
own_port = 8080
|
||||||
|
|
||||||
neighbours = Neighbours(own_process=Member(own_ip, own_port))
|
neighbours = Neighbours(own_process=Member("0.0.0.0", own_port))
|
||||||
game_state = GameState(neighbours)
|
game_state = GameState(neighbours)
|
||||||
server = Server(neighbours, game_state)
|
server = Server(neighbours, game_state)
|
||||||
|
|
||||||
n_direction = Direction.LEFT
|
n_direction = Direction.LEFT
|
||||||
if len(args) > 5:
|
if len(args) > 4:
|
||||||
n_direction = args[5]
|
n_direction = args[4]
|
||||||
if len(args) >= 5:
|
if len(args) >= 4:
|
||||||
n_ip = args[3]
|
n_ip = args[2]
|
||||||
n_port = int(args[4])
|
n_port = int(args[3])
|
||||||
neighbours.connect(Direction[n_direction], n_ip, n_port)
|
neighbours.connect(Direction[n_direction], n_ip, n_port)
|
||||||
|
|
||||||
serverThread = threading.Thread(target=server.start)
|
serverThread = threading.Thread(target=server.start)
|
||||||
|
|
67
README.md
67
README.md
|
@ -4,52 +4,12 @@ Implementierung des berühmten [Conway's Game of Life](https://en.wikipedia.org/
|
||||||
Jeder Teilnehmer hat einen Bereich in dem er Game of Life berechnet und seine Kanten mit den andren Teilnehmer austauscht.
|
Jeder Teilnehmer hat einen Bereich in dem er Game of Life berechnet und seine Kanten mit den andren Teilnehmer austauscht.
|
||||||
Die gesamte Koordination erfolgt dezentral, Kommunikation ist immer p2p-basiert.
|
Die gesamte Koordination erfolgt dezentral, Kommunikation ist immer p2p-basiert.
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
- Python 3+
|
|
||||||
|
|
||||||
```shell
|
|
||||||
pip install -r requirements.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
## Ausführen
|
|
||||||
|
|
||||||
```shell
|
|
||||||
python -m Code.Main own_ip own_port [ neighbour_ip neighbour_port (LEFT|RIGHT) ]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Beispiel (auf lokalem Rechner)
|
|
||||||
|
|
||||||
Als erster Teilnehmer
|
|
||||||
|
|
||||||
```shell
|
|
||||||
python -m Code.Main 0.0.0.0 8080
|
|
||||||
```
|
|
||||||
|
|
||||||
Als zweiter Teilnehmer
|
|
||||||
|
|
||||||
```shell
|
|
||||||
python -m Code.Main 0.0.0.0 8081 0.0.0.0 8080 RIGHT
|
|
||||||
```
|
|
||||||
|
|
||||||
Als dritter Teilnehmer
|
|
||||||
|
|
||||||
```shell
|
|
||||||
python -m Code.Main 0.0.0.0 8082 0.0.0.0 8080 LEFT
|
|
||||||
```
|
|
||||||
|
|
||||||
### Mit zwei Teilnehmern auf dem lokalen Rechner
|
|
||||||
|
|
||||||
```shell
|
|
||||||
python -m Code.Main 0.0.0.0 8080 & sleep 2 && python -m Code.Main 0.0.0.0 8081 0.0.0.0 8080 RIGHT
|
|
||||||
```
|
|
||||||
|
|
||||||
## Einstieg
|
## Einstieg
|
||||||
|
|
||||||
Um an dem Spiel teilzunehmen, muss jeder Teilnehmer (außer der erste) beim Starten der Anwendung die IP-Adresse und den
|
Um an dem Spiel teilzunehmen, muss jeder Teilnehmer (außer der erste) beim Starten der Anwendung die IP-Adresse und den
|
||||||
Port eines anderen Teilnehmers angeben, mit dem er sich verbinden will.
|
Port eines anderen Teilnehmers angeben, mit dem er sich verbinden will.
|
||||||
Zusätzlich muss die Richtung der Kante, mit welcher er sich mit diesem verbinden will, angegeben werden.
|
Zusätzlich muss die Richtung der Kante, mit welcher er sich mit diesem verbinden will, angegeben werden.
|
||||||
Da jeder Teilnehmer an jeder seiner Kanten maximal mit einem anderen Teilnehmer verbunden sein kann, ist es möglich,
|
Da jeder Teilnehmer an jeder seiner Kanten maximal mit einem anderen Teilnehmer verbunden sein kann, ist es möglich,
|
||||||
dass die Kante, die beim Einstieg gewählt wird, bereits besetzt ist.
|
dass die Kante, die beim Einstieg gewählt wird, bereits besetzt ist.
|
||||||
Ist dies der Fall, wird der Anfragende automatisch an denjenigen weitergeleitet, der diese Kante besetzt.
|
Ist dies der Fall, wird der Anfragende automatisch an denjenigen weitergeleitet, der diese Kante besetzt.
|
||||||
Dies passiert so lange bis eine freie Kante gefunden wird und sich somit zwei Teilnehmer verbinden.
|
Dies passiert so lange bis eine freie Kante gefunden wird und sich somit zwei Teilnehmer verbinden.
|
||||||
|
@ -59,35 +19,30 @@ verbunden wird, sondern nur, dass man räumlich **rechts** von Teilnehmer 1 lieg
|
||||||
![Schema Verbindungsaufbau](./images/Verbindungsaufbau.drawio.svg)
|
![Schema Verbindungsaufbau](./images/Verbindungsaufbau.drawio.svg)
|
||||||
|
|
||||||
## Suche
|
## Suche
|
||||||
|
|
||||||
Die Suche ist recht simpel.
|
Die Suche ist recht simpel.
|
||||||
Jeder Teilnehmer kennt nur die Knoten, welche die für ihn relevanten Informationen haben und diese verändern sich im Laufe
|
Jeder Teilnehmer kennt nur die Knoten, welche die für ihn relevanten Informationen haben und diese verändern sich im Laufe
|
||||||
der Zeit auch nicht.
|
der Zeit auch nicht.
|
||||||
|
|
||||||
## Verbreitung
|
## Verbreitung
|
||||||
|
Eine relevante Information, die an das gesamte Netz verbreitet werden muss, ist eine Zustandsänderung bezüglich der
|
||||||
Eine relevante Information, die an das gesamte Netz verbreitet werden muss, ist eine Zustandsänderung bezüglich der
|
|
||||||
Pausierung der Simulation.
|
Pausierung der Simulation.
|
||||||
Hierfür wird einfaches Flooding verwendet.
|
Hierfür wird einfaches Flooding verwendet.
|
||||||
D.h. jeder Teilnehmer schickt den neuen Zustand an alle seine Nachbarn und diese senden ihn wiederum an ihre Nachbarn.
|
D.h. jeder Teilnehmer schickt den neuen Zustand an alle seine Nachbarn und diese senden ihn wiederum an ihre Nachbarn.
|
||||||
Da es nur zwei mögliche Zustände für den Pause-Zustand geben kann, ist Flooding ausreichend effizient, zyklische Nachrichten
|
Da es nur zwei mögliche Zustände für den Pause-Zustand geben kann, ist Flooding ausreichend effizient, zyklische Nachrichten
|
||||||
werden vermieden, indem ein Teilnehmer die Information nicht mehr weiterleitet, wenn er sie bereits bekommen hat, sich also
|
werden vermieden, indem ein Teilnehmer die Information nicht mehr weiterleitet, wenn er sie bereits bekommen hat, sich also
|
||||||
schon im richtigen Zustand befindet.
|
schon im richtigen Zustand befindet.
|
||||||
|
|
||||||
## Zeitliche Synchronisation
|
## Zeitliche Synchronisation
|
||||||
|
Um sicherzustellen, dass alle Teilnehmer gleichzeitig den Entwicklungsschritt durchführen und somit der Randaustausch auch
|
||||||
Um sicherzustellen, dass alle Teilnehmer gleichzeitig den Entwicklungsschritt durchführen und somit der Randaustausch auch
|
|
||||||
korrekt funktioniert, wird eine vereinfachte Version von Lamport Clocks verwendet.
|
korrekt funktioniert, wird eine vereinfachte Version von Lamport Clocks verwendet.
|
||||||
Jeder Prozess hat einen Counter, den er bei jedem Entwicklungsschritt um eins erhöht.
|
Jeder Prozess hat einen Counter, den er bei jedem Entwicklungsschritt um eins erhöht.
|
||||||
Da für jeden Entwicklungsschritt zuerst die Ränder der benachbarten Teilenehmer abgefragt werden müssen und dies blockieriend
|
Da für jeden Entwicklungsschritt zuerst die Ränder der benachbarten Teilenehmer abgefragt werden müssen und dies blockieriend geschieht, sind alle Teilnehmer zu jedem Zeitpunkt um maximal 1 bezüglich ihres Counters versetzt.
|
||||||
geschieht, sind alle Teilnehmer zu jedem Zeitpunkt um maximal 1 bezüglich ihres Counters versetzt.
|
Damit man jedoch mit seinem Entwicklungsschritt nicht warten muss, bis alle Nachbar den Rand angefragt haben, hält jeder Prozess eine Kopie seine Randes vom vorherigen Zeitpunkt.
|
||||||
Damit man jedoch mit seinem Entwicklungsschritt nicht warten muss, bis alle Nachbar den Rand angefragt haben, hält jeder
|
Bei der Anfrage nach dem Rand wird der nachgefragte Counter mitgeschickt, dieser muss dem aktuellen oder dem vorherigen Counter entsprechen oder um eins größer sein, als der aktuelle Counter.
|
||||||
Prozess eine Kopie seine Randes vom vorherigen Zeitpunkt.
|
Ist der angefragte Counter um eins größer als der aktuelle, liegt also quasi in der Zukunft, wird der Request blockiert, bis der Angefragte den nächsten Entwicklungsschritt durchgeführt hat.
|
||||||
Bei der Anfrage nach dem Rand wird der nachgefragte Counter mitgeschickt, dieser muss dem aktuellen oder dem vorherigen
|
|
||||||
Counter entsprechen oder um eins größer sein, als der aktuelle Counter.
|
|
||||||
Ist der angefragte Counter um eins größer als der aktuelle, liegt also quasi in der Zukunft, wird der Request blockiert,
|
|
||||||
bis der Angefragte den nächsten Entwicklungsschritt durchgeführt hat.
|
|
||||||
Somit wird das gesamte Game of Life nur so schnell ausgeführt, wie der langsamste Teilenehmer ist.
|
Somit wird das gesamte Game of Life nur so schnell ausgeführt, wie der langsamste Teilenehmer ist.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- LocalWords: Counter
|
<!-- LocalWords: Counter
|
||||||
-->
|
-->
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
pygame~=2.1.2
|
|
||||||
requests~=2.27.1
|
|
Loading…
Reference in New Issue