diff --git a/client.py b/client.py
index a609e05aa36949c224addcf55602bb7131db93e6..494c50822ffb3413f0caa7156f6bdcf51ab27525 100644
--- a/client.py
+++ b/client.py
@@ -1,30 +1,88 @@
 import socket
 import threading
+from datetime import datetime
 
-def receive_messages():
-    while True:
-        try:
-            # Empfange Nachricht vom Server
-            data = client_socket.recv(1024)
-            print(data.decode('utf-8'))
-        except:
-            break
-
-# Client-Konfiguration
-host = '127.0.0.1'
-port = 5555
-
-# Verbinde zum Server
-client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-client_socket.connect((host, port))
-print(f'Du bist jetzt im Chat')
-
-
-# Starte einen Thread, um Nachrichten vom Server zu empfangen
-receive_thread = threading.Thread(target=receive_messages)
-receive_thread.start()
-
-# Haupt-Thread zum Senden von Nachrichten
-while True:
-    message = input()
-    client_socket.send(message.encode('utf-8'))
+MULTICAST_GROUP_IP = '224.1.1.1'
+
+# Broadcast address and port
+
+CLIENT_MULTICAST_PORT = 5973
+
+# Local host information
+MY_HOST = socket.gethostname()
+MY_IP = socket.gethostbyname(MY_HOST)
+
+
+class Client():
+    def __init__(self):
+        self.currentLeader = ''
+        self.server_socket = None
+
+    # print the current date and time
+    def printwt(self, msg):
+        current_date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
+        print(f'[{current_date_time}] {msg}')    
+
+    # dynamic discoverey: client sends request to server group and gets the IP of server as reply
+    def MulticastSendAndReceive(self):
+        # Create a UDP socket
+        multicast_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+
+        # Set the time-to-live for messages to 1 so they do not go past the local network segment
+        multicast_socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 1)
+
+        # Send message on multicast address
+        message = 'New client wants to connect: ' + MY_IP
+        multicast_socket.sendto(str.encode(message), (MULTICAST_GROUP_IP, CLIENT_MULTICAST_PORT))
+
+        self.printwt("Sent my IP to server group")
+
+        while True:     
+            try:
+                # receive reply data (server IP) from the other participants
+                reply, addr = multicast_socket.recvfrom(1024)
+
+                if reply:
+                    # decode received data
+                    reply_addr = reply.decode()
+                    self.currentLeader = reply_addr
+                    self.printwt(f'Got Leader address: {self.currentLeader}')
+
+                    # Connect to the server using TCP
+                    self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+                    self.server_socket.connect((self.currentLeader, 5555))
+                    print("You have entered the chat room")
+
+                     # Starte einen Thread, um Nachrichten zu empfangen
+                    receive_thread = threading.Thread(target=self.receive_messages)
+                    receive_thread.start()
+
+                    # Haupt-Thread zum Senden von Nachrichten
+                    while True:
+                        message = input()
+                        timestamped_message = f'[{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}] {message}'
+                        self.server_socket.send(timestamped_message.encode('utf-8'))
+                        
+            except socket.timeout:
+                pass
+
+    def receive_messages(self):
+        while True:
+            try:
+                data = self.server_socket.recv(1024)
+                if not data:
+                    break
+                print(data.decode('utf-8'))
+            except:
+                break
+
+
+
+
+# starting all simultaneously working procedures
+if __name__ == "__main__":
+    client = Client()
+
+    thread1 = threading.Thread(target = client.MulticastSendAndReceive)
+    thread1.start()
+    thread1.join()
\ No newline at end of file
diff --git a/server.py b/server.py
index 0183a099b94b3e22dfb00c2075d5861b763de6f1..e5635903724c93c467e57370598fa7d5294fd086 100644
--- a/server.py
+++ b/server.py
@@ -1,59 +1,219 @@
 import socket
 import threading
+from datetime import datetime
+import time
+import struct
 
-def handle_client(client_socket, client_address):
-    while True:
-        try:
-            # Empfange Nachricht vom Client
-            data = client_socket.recv(1024)
-            if not data:
+MULTICAST_GROUP_IP = '224.1.1.1'
+
+# Listening port Server Discovery
+SERVER_MULTICAST_PORT = 5974
+
+# Listening port Client Discovery
+CLIENT_MULTICAST_PORT = 5973
+
+# Local host information
+MY_HOST = socket.gethostname()
+MY_IP = socket.gethostbyname(MY_HOST)
+
+
+class Server():
+    def __init__(self):
+        self.leader_IP = '' # fix the leader IP
+        self.serverList = [] # list if servers and their addresses
+        self.clients = []
+        self.informServer = False
+        self.isLeader = False  # New variable to track if the server is the leader
+        
+
+    def printwt(self, msg):
+        current_date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
+        print(f'[{current_date_time}] {msg}')
+
+    
+    def print_group_view(self):
+        print("Group view is:", self.serverList)
+
+
+        #This function enables the server to listen to the server multicast port and reply the ip address
+    def MulticastListenAndReply(self):
+
+        # if my IP is not in the server list add it
+        if MY_IP not in self.serverList:
+            self.serverList.append(MY_IP)
+
+        # create socket bind to server address
+        multicast_listen_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        multicast_listen_sock.bind(('', SERVER_MULTICAST_PORT))
+
+        # tell the os to add the socket to the multicast group
+        multicast_group = socket.inet_aton(MULTICAST_GROUP_IP)
+        mreg = struct.pack('4sL', multicast_group, socket.INADDR_ANY)
+        multicast_listen_sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreg)
+
+        
+        while True:
+    
+                data, address = multicast_listen_sock.recvfrom(1024)
+
+                if data:
+                    newServer_address = data.decode()
+                    self.printwt(f'New participant wants to connect: {newServer_address}')
+                    self.isLeader = False
+
+                    # if the decoded address is not in the server list add it and print the list
+
+                    if newServer_address not in self.serverList:
+                        self.serverList.append(newServer_address)
+
+                    reply_message = MY_IP
+                    multicast_listen_sock.sendto(str.encode(reply_message), address)
+ 
+                    self.printwt('Replied my IP to new participant')
+
+        
+
+                time.sleep(1)
+                self.print_group_view()
+                self.printwt(f'The current leader IP is: {self.leader_IP}')
+            
+
+        #this function enables the server to send a multicast to the server group and receive the answers of existing members
+    def MulticastSendAndReceive(self):
+    
+        # create socket
+        multicast_group = (MULTICAST_GROUP_IP, SERVER_MULTICAST_PORT)
+        multicast_send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        # Set a timeout so the socket does not block indefinitely when trying to receive data.
+        multicast_send_sock.settimeout(2)
+
+         # Set the time-to-live for messages to 1 so they do not go past the local network segment.
+        multicast_send_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 1)
+
+        message = MY_IP
+        multicast_send_sock.sendto(message.encode(), multicast_group)
+        self.printwt("Sent my IP to server group")
+
+        # if my IP is not in the server list add it
+        if MY_IP not in self.serverList:
+            self.serverList.append(MY_IP)
+        
+        # listen for IPs from existing servers
+        maxLoop = 5
+        currentLoop = 0
+
+        # Anzahl der eingehenden Antworten initialisieren
+        num_responses = 0
+        
+        while currentLoop < maxLoop:
+            print("Waiting for responses...")  # Debug-Ausgabe
+            while True:     
+                currentLoop += 1
+
+                try:
+                    # receive reply data from the other participants
+                    reply, address = multicast_send_sock.recvfrom(1024)
+
+                    if reply:
+                        reply_address = reply.decode()
+
+                        # Debug-Ausgabe
+                        print(f"Received response from: {reply_address}")
+
+                        # if reply address is not in the server list, add it
+                        if reply_address not in self.serverList:
+                            self.serverList.append(reply_address)
+
+                        # Erhöhe die Anzahl der eingehenden Antworten
+                        num_responses += 1
+                        print(f"Current server list: {self.serverList}")  # Debug-Ausgabe
+
+                except socket.timeout:
+                    break
+
+        if num_responses == 1:     
+            multicast_send_sock.close()
+            self.isLeader = True
+            self.leader_IP = MY_IP # Hier wird die IP-Adresse des Leaders zugewiesen
+            self.printwt(f'I am the only server in the system, so the leader IP is: {self.leader_IP}')
+            time.sleep(1)
+
+
+        self.print_group_view()
+        
+
+    # Listen to client multicast (request) and reply with Server IP
+    def ListenForClientAndReply(self):
+        # Create a UDP socket
+        listen_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        # Enable reusing addresses
+        listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        # Bind socket to address and port
+        listen_socket.bind((MY_IP, CLIENT_MULTICAST_PORT))
+
+        # tell the os to add the socket to the multicast group
+        multicast_group = socket.inet_aton(MULTICAST_GROUP_IP)
+        mreg = struct.pack('4sL', multicast_group, socket.INADDR_ANY)
+        listen_socket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreg)
+
+        # print("Listening to multicast messages")
+
+        # Receiving multicast massage
+        while True:
+            data, addr = listen_socket.recvfrom(1024)
+
+            if data:
+                self.printwt(data.decode())
+
+        # if Iam the leader, answer the client including my IP
+                if MY_IP == self.leader_IP:
+                    reply_message = MY_IP
+                    listen_socket.sendto(str.encode(reply_message), addr)
+                    self.printwt('Replied my IP to new client')
+
+    def handle_client(self, client_socket, client_address):
+        self.clients.append(client_socket)
+
+        while True:
+            try:
+                data = client_socket.recv(1024)
+                if not data:
+                    break
+                self.multicast(data, client_socket)
+
+            except:
+                self.clients.remove(client_socket)
                 break
 
-            # Sende die empfangene Nachricht an alle anderen Clients
-            broadcast(data, client_socket, client_address)
-        except:
-            break
-
-    # Client-Socket schließen
-    client_socket.close()
-
-def broadcast(message, sender_socket, sender_address):
-    for client in clients:
-        try:
-            # Sende die Nachricht an alle Clients, außer an den Absender
-            if client != sender_socket:
-                client.send(f"{sender_address}: {message}".encode('utf-8'))
-        except:
-            # Entferne defekte Verbindungen
-            clients.remove(client)
-
-# Server-Konfiguration
-host = '192.168.2.42'
-port = 5555
-
-# Socket erstellen und binden
-server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-server_socket.bind((host, port))
-server_socket.listen(5)
-
-print(f'Server lauscht auf {host}:{port}')
-
-# Liste für die verbundenen Clients
-clients = []
-servers = [server_socket]
-
-while True:
-    # Warten auf eine Verbindung
-    connection_socket, client_address = server_socket.accept()
-
-    # Wenn eine Verbindung von einem anderen Server kommt, füge ihn zur Serverliste hinzu
-    if connection_socket != server_socket:
-        servers.append(connection_socket)
-    else:
-        # Neuen Thread für jeden verbundenen Client erstellen
-        client_thread = threading.Thread(target=handle_client, args=(connection_socket, client_address))
-        client_thread.start()
-
-        # Client-Socket zur Liste hinzufügen
-        clients.append(connection_socket)
+    def multicast(self, message, sender_socket):
+        for client in self.clients:
+            try:
+                if client != sender_socket:
+                    client.send(message)
+            except:
+                self.clients.remove(client)
+
+
+# starting all simultaneously working procedures
+if __name__== '__main__':
+    server = Server()
+
+    thread2 = threading.Thread(target = server.MulticastListenAndReply)
+    thread2.start()
+
+    thread3 = threading.Thread(target = server.MulticastSendAndReceive)
+    thread3.start()
+
+    thread1 = threading.Thread(target = server.ListenForClientAndReply)
+    thread1.start()
+
+    # Socket erstellen und binden
+    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    server_socket.bind((MY_IP, 5555))
+    server_socket.listen(5)
+
+    while True:
+        client_socket, client_address = server_socket.accept()
 
+        client_thread = threading.Thread(target=server.handle_client, args=(client_socket, client_address))
+        client_thread.start()
\ No newline at end of file