diff --git a/client.py b/client.py index d2952bfaf54e5bd15d6871cd474add50c7c1d6f4..c2f81ace20513a8d6a720ef38d74cc6c2e1ad5f2 100644 --- a/client.py +++ b/client.py @@ -65,6 +65,26 @@ class Client(): except socket.timeout: pass + def discover_group_members(self): + # Send a broadcast message to discover group members + group_discovery_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + group_discovery_socket.settimeout(3) # Set timeout to 3 seconds + group_discovery_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + group_discovery_socket.sendto(str.encode("Any group members here?"), ('<broadcast>', BROADCAST_PORT)) + + try: + while True: + data, addr = group_discovery_socket.recvfrom(1024) + if data: + group_member_IP = data.decode() + if group_member_IP != MY_IP and group_member_IP not in self.group_members: + self.group_members[group_member_IP] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + self.printwt(f'New group member found: {group_member_IP}') + # Respond to the new member with own IP + group_discovery_socket.sendto(str.encode(MY_IP), (group_member_IP, BROADCAST_PORT)) + except socket.timeout: + group_discovery_socket.close() + def receive_messages(self): while True: try: @@ -82,6 +102,11 @@ class Client(): if __name__ == "__main__": client = Client() + # Start a thread to discover group members + discovery_thread = threading.Thread(target=client.discover_group_members) + discovery_thread.start() + + # Start the thread to send and receive messages thread1 = threading.Thread(target = client.BroadcastSendAndReceive) thread1.start() thread1.join() \ No newline at end of file diff --git a/server.py b/server.py index b09e59b3a4e6b095bf77479f87c869606a747365..5b0a5210eb5d2d9b003ac24edac0e1d7e54f4cd9 100644 --- a/server.py +++ b/server.py @@ -1,6 +1,7 @@ import socket import threading from datetime import datetime +import time # Listening port BROADCAST_PORT = 5973 @@ -11,13 +12,22 @@ MY_IP = socket.gethostbyname(MY_HOST) class Server(): def __init__(self): + self.group_members = {} # Dictionary to store group members with their IPs as keys self.leader_IP = '' # fix the leader IP self.clients = [] + 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_members(self): + self.printwt("Current group members:") + for member, timestamp in self.group_members.items(): + self.printwt(f'{member} (joined at {timestamp})') + + # Listen to client broadcast (request) and reply with Server IP def ListenForClientAndReply(self): # Create a UDP socket @@ -38,12 +48,12 @@ class Server(): self.printwt(data.decode()) # if Iam the leader, answer the client including my IP - # if MY_IP == self.leader_IP: - if data: + 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) @@ -58,6 +68,7 @@ class Server(): self.clients.remove(client_socket) break + def broadcast(self, message, sender_socket): for client in self.clients: try: @@ -67,13 +78,44 @@ class Server(): self.clients.remove(client) + def announce_leader(self): + # Send a broadcast message to determine the leader + leader_broadcast_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + leader_broadcast_socket.settimeout(3) # Set timeout to 3 seconds + leader_broadcast_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + leader_broadcast_socket.sendto(str.encode("Who is the leader?"), ('<broadcast>', BROADCAST_PORT)) + + try: + data, addr = leader_broadcast_socket.recvfrom(1024) + if data: + self.leader_IP = addr[0] + self.group_members[self.leader_IP] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + self.printwt(f'Leader elected: {self.leader_IP}') + + except socket.timeout: + # If no response received, assume this server is the leader + self.leader_IP = MY_IP + self.group_members[self.leader_IP] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + self.printwt(f'I am the first server and leader: {self.leader_IP}') + + leader_broadcast_socket.close() + # starting all simultaneously working procedures if __name__== '__main__': server = Server() + # Start a thread to announce the leader + leader_thread = threading.Thread(target=server.announce_leader) + leader_thread.start() + + # Start the thread to listen for client broadcasts thread1 = threading.Thread(target = server.ListenForClientAndReply) thread1.start() + # Start a thread to periodically print the group members + print_group_thread = threading.Thread(target=server.print_group_members) + print_group_thread.start() + # Socket erstellen und binden server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind((MY_IP, 5555))