import socket import threading from datetime import datetime import time BROADCAST_IP = "192.168.0.255" # Listening port Server Discovery SERVER_BROADCAST_PORT = 5974 # Listening port Client Discovery CLIENT_BROADCAST_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 broadcast port and reply the ip address def BroadcastListenAndReply(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 broadcast_listen_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) broadcast_listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) broadcast_listen_sock.bind((MY_IP, SERVER_BROADCAST_PORT)) while True: data, address = broadcast_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 broadcast_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 broadcast to the server group and receive the answers of existing members def BroadcastSendAndReceive(self): # create socket broadcast_group = (BROADCAST_IP, SERVER_BROADCAST_PORT) broadcast_send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) broadcast_send_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) broadcast_send_sock.settimeout(2) # ... message = MY_IP broadcast_send_sock.sendto(message.encode(), broadcast_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 = broadcast_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: broadcast_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 broadcast (request) and reply with Server IP def ListenForClientAndReply(self): # Create a UDP socket listen_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Set the socket to broadcast and enable reusing addresses listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Bind socket to address and port listen_socket.bind((MY_IP, CLIENT_BROADCAST_PORT)) # print("Listening to broadcast messages") # Receiving broadcast 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.broadcast(data, client_socket) except: self.clients.remove(client_socket) break def broadcast(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.BroadcastListenAndReply) thread2.start() thread3 = threading.Thread(target = server.BroadcastSendAndReceive) 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()