diff --git a/2024-12-16_Server.py b/2024-12-16_Server.py
new file mode 100644
index 0000000000000000000000000000000000000000..82dab6937ac8be40c1beb6f3553d9698c7e599ac
--- /dev/null
+++ b/2024-12-16_Server.py
@@ -0,0 +1,317 @@
+#Ring testebn
+#Forming a Ring
+
+import time
+import threading
+from uuid import uuid4
+import socket
+import uuid
+import json
+import neighbour
+import multiprocessing
+import os
+from multiprocessing import Manager
+from collections import deque
+
+broadcast_ip = '255.255.255.255'
+broadcast_port = 55555
+election_port= 55559
+
+
+#dict member = {"uuid": {"IP",}}
+#Definition Atribute
+global members_UUID
+global member_IP
+members_UUID = [] #List for members in the ring
+member_IP = [] #List for ip Adresses of the members
+broadcast_ip = "255.255.255.255" #Broadcast-adress in the Network
+port = 12348 #Port that is used for the discovery of new server participants
+server_ip = "0.0.0.0" #IP that enables the server to receive all messages that are passed to the port
+myuuid = uuid.uuid4()
+my_ID = str(myuuid) #Creating a unique ip Adress using uuid4
+ringport = 12343
+election_socket = 12345
+hostname = socket.gethostname()
+ip_address = socket.gethostbyname(hostname) ##### Für Tests anpassen "127.0.0.1"
+participating = False
+is_leader = False
+Leader = False
+ELECTION = 0
+NEW_LEAD = 1
+
+#Muss dauerhaft erfolgen
+def lausche_update_Ring():
+ global member_IP
+
+ # Erstellen eines UDP-Sockets
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ # Setze den Socket in den Broadcast-Modus Wöfür Frage MF?????
+ #sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
+ # Sende die Nachricht an die Broadcast-Adresse
+ sock.bind((ip_address, ringport))
+ while True:
+ try:
+ data, addr = sock.recvfrom(1024) # Antwort empfangen
+ member_IP2 = json.loads(data.decode())
+ #Abgleich, ob Member_IP2 gleich Member_Ip ist
+ if member_IP2 == member_IP:
+ print(f"Ring Update bereits erhalten: {member_IP}")
+ else:
+ member_IP = member_IP2
+ print(f"Ring Update erhalten: {member_IP}")
+ send_update_to_ring()
+ #nachricht_update_ring()
+ except json.JSONDecodeError:
+ print("Fehler beim Decodieren der JSON-Daten.")
+
+
+#Function of Leader. Server is listeng to the Port to greet new servers and Update Ring Topology
+def new_server_in_ring():
+ global members_UUID
+ global member_IP
+
+ # Erstellen eines UDP-Sockets
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ # Setze den Socket in den Broadcast-Modus
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
+ # Binde den Socket an die Adresse und den Port
+ sock.bind(("0.0.0.0", port))
+ print("Server läuft und wartet auf Broadcast-Nachrichten von neuen Servern.")
+ while True:
+ #Lauscht ob es ene Nachricht von anderen servern erhält
+ data, addr = sock.recvfrom(1024) # Puffergröße 1024 Bytes
+ print(f"Nachricht empfangen von {addr}: {data.decode()}")
+ msg = 'Es gibt bereits server'
+ new_server_ip, new_server_port = addr
+ new_IP = data.decode()
+ new_IP = new_IP.split(": ")[1]
+
+ # ??? notwendig ???
+ #Prüfen ob die ID bereis vorhanden ist und Server nur kurz die Verbindung verloren hat. Kann eigemtlich nich eintreten, da ID immer neu generiert wird
+ if new_IP in member_IP:
+ #msg = f"Welcome Back. Aktueller Ring: {json.dumps(members)}".encode()
+ Nachricht = json.dumps(member_IP).encode()
+ else:
+ #members_UUID.append(new_ID) ####UUID wird in Nachricht nicht mehr übergeben
+ member_IP.append(new_IP)
+ sock.sendto(msg.encode(), (new_IP, new_server_port))
+ #print(f"Members des Rings sind: {members_UUID}")
+ print(f"Der neue IP_Ring ist: {member_IP}")
+
+ #Ring Update losschicken
+ send_update_to_ring()
+
+
+
+#Server tritt bei und macht sich für andere Server bemerkbar
+def server_enters():
+ global members_UUID
+ msg = f"Ich bin neu: {ip_address}".encode() #Greeting message of the server entering the chat
+ # Erstellen eines UDP-Sockets
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ # Setze den Socket in den Broadcast-Modus
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
+ # Sende die Nachricht an die Broadcast-Adresse
+ sock.sendto(msg, (broadcast_ip, port))
+ # Warte etwas auf eine Antwort
+ sock.settimeout(2)
+ try:
+ data, addr = sock.recvfrom(1024) # Antwort empfangen
+ print(f"Antwort von {addr}: {data.decode()}")
+ #lausche_update_Ring() Nicht Notwendig, da Funktion dauerhaft im Hintergrund erfolgt....
+ sock.close()
+ #Liste der Members wird dem Neuzugang gesendet, Es wird geprüft, ob die json Datei ausgelesen werden kann. Json wird genutzt um Liste Vollständig zu übergeben
+ #try:
+ #members_UUID = json.loads(data.decode())
+ #print(f"Der neue Ring ist: {members_UUID}")
+ #print(f"Der neue IP_Ring ist: {member_IP}")
+
+ #nachricht_update_ring()
+ #except json.JSONDecodeError:
+ #print("Fehler beim Decodieren der JSON-Daten.")
+
+ #Übergabe der Ring Teilnehmer durch den Server an Alle anderen Teilnehnmer!!
+ except socket.timeout:
+ #If no answer is received the server sets itself as leader
+ print(f"Keine Antwort erhalten. Ich bin jetzt der Leader. Meine IP: {ip_address}")
+ #Leader fügt sich selbst als Teilnehmer in den Ring ein
+ members_UUID.append(my_ID)
+ member_IP.append(ip_address)
+ sock.close()
+ is_leader.set_value(True)
+ new_server_in_ring()
+
+#Server tritt in den Ring ein/formt den Ring
+def send_update_to_ring():
+ global member_IP
+ right_neighbour = neighbour.get_neighbour(member_IP, ip_address, 'right')
+ if not right_neighbour:
+ print("No left neighbour to send updates.")
+ return
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ data = json.dumps(member_IP).encode()
+ try:
+ sock.sendto(data, (right_neighbour , ringport))
+ except Exception as e:
+ print(f"Error sending data: {e}")
+ sock.close()
+
+
+##############################################################
+##############################################################
+##############################################################
+
+
+
+
+def start_election():
+ right_neighbour = neighbour.get_neighbour(member_IP, ip_address, 'right')
+ print("{} is starting an election.".format(myuuid))
+ #Server nimmt an Election Teil
+ participating = True
+ #Nachricht wird an den Server neben an gesendet
+ msg = f"{ELECTION}: {myuuid}".encode('utf-8')
+ #Msg encoden? Variable setzen?
+ send_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
+ send_socket.sendto(msg,(right_neighbour,election_socket)) ########Problem an dieser Stelle??
+ #data,addr=send_socket.recvfrom(4096)
+ #Was passiert wenn diese Nachricht nicht ankommt?
+ send_socket.close()
+
+
+def accept(group,erhaltene_uuid):
+ right_neighbour = neighbour.get_neighbour(member_IP, ip_address, 'right')
+ if group == ELECTION:
+ #Abgleich der erhaltenen Uuid mit der eigenen uuid
+ if erhaltene_uuid > myuuid:
+ print("{} is forwarding without updates.".format(myuuid))
+ participating = True
+ msg = f"{ELECTION}: {erhaltene_uuid}".encode()
+ #Weitergabe der höheren uuid
+ send_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
+ send_socket.sendto(msg,(right_neighbour,election_socket))
+ #Was passiert wenn diese Nachricht nicht ankommt?
+ send_socket.close()
+ if erhaltene_uuid < myuuid:
+ print("{} is updating and forwarding.".format(myuuid))
+ participating = True
+ msg = f"{ELECTION}: {myuuid}".encode()
+ #Weitergabe der höheren uuid
+ send_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
+ send_socket.sendto(msg,(right_neighbour,election_socket))
+ #Was passiert wenn diese Nachricht nicht ankommt?
+ send_socket.close()
+ if erhaltene_uuid == myuuid:
+ print("{} starts acting as a leader!".format(myuuid))
+ participating = False
+ #is_leader = True
+ is_leader.set_value(True)
+ leader = myuuid
+ msg = f"{NEW_LEAD}: {myuuid}".encode()
+ #Weitergabe der höheren uuid
+ send_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
+ send_socket.sendto(msg,(right_neighbour,election_socket))
+ #Was passiert wenn diese Nachricht nicht ankommt?
+ send_socket.close()
+ if group == NEW_LEAD:
+ if erhaltene_uuid == myuuid:
+ return
+ if erhaltene_uuid != myuuid:
+ print("{} acknowledged new leader.".format(myuuid))
+ is_leader.set_value(False)
+ leader = myuuid
+ msg = f"{NEW_LEAD}: {erhaltene_uuid}".encode()
+ #Weitergabe der höheren uuid
+ send_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
+ send_socket.sendto(msg,(right_neighbour,election_socket))
+ #Was passiert wenn diese Nachricht nicht ankommt?
+ send_socket.close()
+
+
+#zuhören
+
+#start_election()
+def zuhören_election():
+ sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
+ sock.bind((ip_address,election_socket))
+ while True:
+ data,addr=sock.recvfrom(4096)
+ übernahme = data.decode('utf-8')
+ #message = ("Hello i am server").encode('utf-8')
+ #Für Piggiback Acn nutzen?
+ #sock.sendto(message,addr)
+ grouprec = int(übernahme.split(": ")[0])
+ #print(übernahme)
+ #print((übernahme.split(": ")[1]))
+ erhaltene_uuid2 = uuid.UUID((übernahme.split(": ")[1]))
+ accept(grouprec,erhaltene_uuid2)
+
+
+def frage_benutzer():
+ # Den Benutzer fragen, ob er die Funktion ausführen möchte
+ antwort = input("Möchten Sie die Funktion ausführen? (Ja/Nein): ").strip().lower()
+ if antwort == 'ja':
+ start_election()
+ else:
+ print("Die Funktion wurde nicht ausgeführt.")
+
+
+
+#######################################################################
+#######################################################################
+#######################################################################
+
+
+
+#####Mit dieser Funktion wird beobachtet, ob sich ein Wert verändert
+class VariableWatcher:
+ def __init__(self):
+ self._value = None # Initialisiert den Wert als None
+ self.observers = [] # Erstellt eine Liste, um die Beobachter zu speichern
+
+ def set_value(self, new_value):
+ self._value = new_value # Setzt den neuen Wert
+ self.notify(new_value) # Benachrichtigt alle Beobachter über den neuen Wert
+
+ def add_observer(self, observer):
+ self.observers.append(observer) # Fügt einen Beobachter zur Liste hinzu
+
+ def notify(self, new_value):
+ for observer in self.observers: # Iteriert durch alle Beobachter
+ observer(new_value) # Ruft die Beobachter mit dem neuen Wert auf
+
+
+
+#Wenn sich der Wert des is_leaders verändert wird diese veränderung hier geprüft
+def callback(new_value):
+ print(f"Variable value changed to: {new_value}") # Callback-Funktion, die aufgerufen wird, wenn sich der Wert ändert
+ if new_value==True:
+ print("Ich übernehme die Aufgaben des leaders")
+ #new_server_in_ring()
+ else:
+ print("Leider bin ich nicht mehr leader")
+
+
+
+
+
+
+if __name__ == "__main__":
+ # Thread 1 und 2 erstellen
+ #thread1 = f"Thread1-{my_ID}"
+ thread1 = threading.Thread(target=server_enters) #Achtung eigentlich nur Leader!!
+ thread2 = threading.Thread(target=lausche_update_Ring)
+ thread3 = threading.Thread(target=frage_benutzer)
+ thread4 = threading.Thread(target=zuhören_election)
+
+ # Starten der Threads
+ thread1.start()
+ thread2.start()
+ thread3.start()
+ thread4.start()
+
+ is_leader = VariableWatcher()
+ is_leader.add_observer(callback) # Fügt die Callback-Funktion als Beobachter hinzu
+
+# Schließe den Socket an welchem Punkt??
+#sock.close()