Compare commits

..

2 Commits

Author SHA1 Message Date
qvalentin c958cc6634
Add own ip as cli arg and add examples to readme 2022-04-12 12:47:26 +02:00
qvalentin f60eaf1da6
Add requirements.txt 2022-04-12 12:21:41 +02:00
3 changed files with 70 additions and 19 deletions

View File

@ -11,6 +11,7 @@ if __name__ == "__main__":
""" """
Getting the args Getting the args
- own ip
- own port - own port
Optional: A neighbour: Optional: A neighbour:
@ -22,22 +23,25 @@ if __name__ == "__main__":
args = sys.argv args = sys.argv
print(args) print(args)
if len(args) >= 2: if len(args) >= 3:
own_port = int(args[1]) own_ip = 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("0.0.0.0", own_port)) neighbours = Neighbours(own_process=Member(own_ip, 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) > 4: if len(args) > 5:
n_direction = args[4] n_direction = args[5]
if len(args) >= 4: if len(args) >= 5:
n_ip = args[2] n_ip = args[3]
n_port = int(args[3]) n_port = int(args[4])
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)

View File

@ -4,12 +4,52 @@ 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.
@ -19,30 +59,35 @@ 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 geschieht, sind alle Teilnehmer zu jedem Zeitpunkt um maximal 1 bezüglich ihres Counters versetzt. Da für jeden Entwicklungsschritt zuerst die Ränder der benachbarten Teilenehmer abgefragt werden müssen und dies blockieriend
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. geschieht, sind alle Teilnehmer zu jedem Zeitpunkt um maximal 1 bezüglich ihres Counters versetzt.
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. Damit man jedoch mit seinem Entwicklungsschritt nicht warten muss, bis alle Nachbar den Rand angefragt haben, hält jeder
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. Prozess eine Kopie seine Randes vom vorherigen Zeitpunkt.
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
--> -->

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
pygame~=2.1.2
requests~=2.27.1